7

很简单的问题。这是有效的 C++11 吗?

struct Foo {
    int bar = 1;
    int baz = bar;
};

GCC (4.7.2) 和 Clang (3.1) 都接受它的迂腐设置:

-std=c++11 -Wall -W -pedantic

英特尔 C++ (13.0.1.117) 没有。它咆哮int baz = bar;着:

错误:非静态成员引用必须相对于特定对象

谁是对的?

如果您想知道,我将它用于这样的代码,它使初始化代码更紧密地结合在一起,而不是将最后一行移到构造函数中:

uint8_t colorR = -1;
uint8_t colorG = -1;
uint8_t colorB = -1;
uint8_t colorA = -1;
GLubyte RGBAVec[4] = {colorR, colorG, colorB, colorA};
4

1 回答 1

3

5.1p12表示类的非静态数据成员或非静态成员函数的id-expression只能用于:

  • 作为类成员访问 (5.2.5) 的一部分,其中对象表达式引用成员的类或从该类派生的类,或
  • 形成指向成员(5.3.1)的指针,或
  • 在该类或从该类(12.6.2)派生的类的构造函数的mem初始化程序中,或
  • 该类或从该类 (12.6.2) 派生的类的非静态数据成员的大括号或等式初始化程序中,或
  • 如果该 id-expression 表示非静态数据成员并且它出现在未计算的操作数中。

所以是的,这个:

struct Foo {
  int bar = 1;
  int baz = bar;
};

是有效的 C++11。

但要小心订单,因为:

12.6.2p10在非委托构造函数中,初始化按以下顺序进行:

  • 首先,并且仅对于最派生类(1.8)的构造函数,虚拟基类按照它们出现在基类的有向无环图的深度优先从左到右遍历的顺序进行初始化,其中“左- to-right”是派生类base-specifier-list中基类的出现顺序。
  • 然后,直接基类按照它们出现在 base-specifier-list 中的声明顺序进行初始化(无论 mem-initializers 的顺序如何)。
  • 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化 (同样不管 mem-initializers 的顺序)。
  • 最后,执行构造函数体的复合语句

因此,如非静态数据成员初始值设定项提案(问题 3)中所述:

第三个问题是类范围查找可能会将编译时错误变成运行时错误:

struct S {
    int i = j; // ill-formed without forward lookup, undefined behavior with
    int j = 3;
};

(除非被编译器捕获,否则 i 可能会使用未定义的 j 值进行初始化。)

于 2012-12-14T16:44:07.283 回答