来自另一个非静态的非静态成员初始化程序

Nik*_* C. 7 c++ gcc clang icc c++11

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

struct Foo {
    int bar = 1;
    int baz = bar;
};
Run Code Online (Sandbox Code Playgroud)

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

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

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

error: a nonstatic member reference must be relative to a specific object

谁是对的?

如果您想知道,我将此用于此类代码,它将初始化代码放在一起,而不是将最后一行移动到构造函数中:

uint8_t colorR = -1;
uint8_t colorG = -1;
uint8_t colorB = -1;
uint8_t colorA = -1;
GLubyte RGBAVec[4] = {colorR, colorG, colorB, colorA};
Run Code Online (Sandbox Code Playgroud)

Dra*_*rax 3

\n

5.1p12表示类的非静态数据成员或非静态成员函数的id 表达式只能\n 使用:

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

所以是的,这个:

\n\n
struct Foo {\n  int bar = 1;\n  int baz = bar;\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

是有效的 C++11。

\n\n

但要注意顺序,因为:

\n\n
\n

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

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

正如非静态数据成员初始值设定项提案(问题 3)中所指定的那样:

\n\n
\n

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

\n\n
struct S {\n    int i = j; // ill-formed without forward lookup, undefined behavior with\n    int j = 3;\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n
\n