【问题标题】:How to make initializer list and class member initializer work together?如何使初始化器列表和类成员初始化器一起工作?
【发布时间】:2013-01-29 08:40:42
【问题描述】:

以下代码在 gcc-4.7.1 和 clang-3.2 下都不能使用 -std=c++11 编译。所以我觉得我做错了什么。但我不知道为什么。有人可以给我一个提示吗?基本上,如果我删除 X 的类内成员初始化程序,它就可以工作。那么为什么初始化器列表不能与类内成员初始化器一起使用呢?

struct X {
    int x = 1;
    int y = 1;
};

int main() {
    X x = {1, 2};
}

gcc 编译错误:

a.cpp: In function 'int main()':
a.cpp:7:16: error: could not convert '{1, 2}' from '<brace-enclosed initializer list>' to 'X'

【问题讨论】:

  • @IvayloStrandjev,正如我提到的,是的。
  • 会员声明中的= 1; 总是让人重复。
  • 问题是当你有初始化器时,它形成了X() : x{1}, y{1} {}的等价物,我敢打赌这就是聚合初始化不起作用的原因。
  • @chris 我只是在想同样的事情。使用此类类内初始化程序时,可能会出现带有预构建初始化程序列表的默认构造函数。
  • @chris 你又是对的。 X 不是聚合,根据 8.5.1。请参阅对我的答案的编辑。

标签: c++ c++11


【解决方案1】:

通过在声明点初始化非静态数据成员,您的类不再是聚合(请参阅 8.5.1 聚合[decl.init.aggr])。

一种解决方法是添加一个双参数构造函数。这允许您使用初始化器列表初始化,它允许与聚合初始化相同的语法,即使您的类在技术上不是聚合。

struct X {
  X(int x, int y) : x(x), y(y) {}
    int x = 1;
    int y = 1;
};

int main() 
{
    X x1{1, 2};
    X x2 = {1,2};
}

注意:对于 C++1y,这些规则已经放宽,这意味着您的类型确实是一个聚合。

【讨论】:

  • +1 供参考。我怀疑这样的事情,但你打败了我:p
  • "这允许您使用聚合初始化" -- 这并不完全正确,您现在所做的称为 list-initialization
  • @Xeo,真的。虽然语法相同:p
  • @Xeo 我改写了我的答案。感谢您的评论。
  • @DwayneRobinson 不,那行不通。但是,对于 C++14,这些规则已经放宽,所以 OP 的类型实际上是一个聚合。我可能会对此添加注释。
猜你喜欢
  • 1970-01-01
  • 2015-09-25
  • 2015-11-28
  • 2016-08-19
  • 2019-09-10
  • 2015-02-28
  • 1970-01-01
  • 2016-06-23
  • 1970-01-01
相关资源
最近更新 更多