【问题标题】:Custom brace initializer自定义大括号初始化器
【发布时间】:2017-08-09 17:31:56
【问题描述】:

假设我有这个结构:

struct MyStruct {
    int field1;
    char *field2;
    MyStruct(int a, char* b): field2(b) {
        field1 = doStuff(a);
    }
    MyStruct(int a): MyStruct(a, nullptr) {}
    ~MyStruct();
}

据我所知,这不是一个聚合,因为我有一些构造函数。

我想要实现的是以自定义方式使用大括号初始化器,这意味着使用这样的代码:

MyStruct x = { 1, "string" };

隐式调用正确的构造函数(在本例中为第一个)。

这有可能吗?

【问题讨论】:

  • initializer_list?顺便说一句...在这种特殊情况下,您可以使用 default argument 来减少代码。
  • 如果你只使用const char*而不是char*,它只是按原样编译。有什么问题?

标签: c++ uniform-initialization list-initialization


【解决方案1】:

你快到了。 MyStruct x = { 1, "string" }; 被称为复制列表初始化。它将尝试使用 braced-init-list

提供的参数从可用的构造函数构造一个MyStruct

您的问题是您的构造函数采用char*,而"string"const char[N],它可以衰减为const char*,而不是char*。所以做出改变的事情

struct MyStruct {
    int field1;
   const char* field2;
    MyStruct(int a, const char* b): field2(b) {
        field1 = a;
    }
    MyStruct(int a): MyStruct(a, nullptr) {}
    ~MyStruct() {}
};

然后

MyStruct x = { 1, "string" };

会工作。如果您想让它更加防弹,您可以将 field2 更改为 std::string 并使用

struct MyStruct {
    int field1;
    std::string field2;
    MyStruct(int a, const std::string& b): field1(a), field2(b) {}
    MyStruct(int a): MyStruct(a, "") {}
    ~MyStruct() {}
};

【讨论】:

  • 如果您需要field2 可以更改,您需要使用std::string 或手动复制字符串。即使您不需要const-ness,您可能仍应使用std::string 或C++17 std::string_view
  • @DanielH 好东西string_view。这是不可变的,所以它是const char*,它没有复制它,因为我认为它并不重要。我错了!需要明确的是,如果 field1 也是恒定的(然后我在 costructor 中有一个 const int a,一切都会继续工作吗?
  • 您可以使用const 值初始化非const 变量。这里的问题是你不能用pointer to *const*初始化一个指向非const指针,因为你可以通过创建的指针改变值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-23
  • 2019-08-04
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
相关资源
最近更新 更多