相关疑难解决方法(0)

C++ 11允许非静态和非const成员的类内初始化.改变了什么?

在C++ 11之前,我们只能对整数或枚举类型的静态const成员执行类内初始化.Stroustrup在他的C++ FAQ中讨论了这个问题,给出了以下示例:

class Y {
  const int c3 = 7;           // error: not static
  static int c4 = 7;          // error: not const
  static const float c5 = 7;  // error: not integral
};
Run Code Online (Sandbox Code Playgroud)

以下推理:

那么为什么存在这些不方便的限制呢?类通常在头文件中声明,并且头文件通常包含在许多翻译单元中.但是,为避免复杂的链接器规则,C++要求每个对象都有唯一的定义.如果C++允许将需要作为对象存储在内存中的实体的类内定义,则该规则将被破坏.

但是,C++ 11放宽了这些限制,允许非静态成员的类内初始化(§12.6.2/ 8):

在非委托构造函数中,如果给定的非静态数据成员或基类未由mem-initializer-id指定(包括没有mem-initializer-list的情况,因为构造函数没有ctor-initializer)然后,实体不是抽象类(10.4)的虚基类

  • 如果实体是具有大括号或等于初始值的非静态数据成员,则按照8.5中的规定初始化该实体;
  • 否则,如果实体是变体成员(9.5),则不执行初始化;
  • 否则,实体默认初始化(8.5).

第9.4.2节还允许非const静态成员的类内初始化,如果它们用说明constexpr符标记的话.

那么我们在C++ 03中受到限制的原因究竟发生了什么?我们只是简单地接受"复杂的链接器规则"或者是否有其他改变使得这更容易实现?

c++ initialization class class-members c++11

80
推荐指数
3
解决办法
9万
查看次数

我的假设是以下格式错误的NDR?但为什么?

[class.mem] / 6

一个类的完整类上下文是
(6.1)函数体,
(6.2)默认参数,
(6.3)noexcept-specifier([except.spec]),
(6.4)合同条件或
(6.5)默认成员初始化器

在类的成员规范内。[?注意:如果嵌套类是在封闭类的成员规范内定义的,则嵌套类的完整类上下文也是任何封闭类的完整类上下文。-?尾注?]

上面突出显示的文本似乎为以下代码段提供了支持:

#include<iostream>
struct A{
    int i = j + 1;
    int j = 1;
};

int main(){
    A a;
    std::cout << a.i << '\n';
    std::cout << a.j << '\n';
}
Run Code Online (Sandbox Code Playgroud)

,并且我希望它能打印出来

2
1
Run Code Online (Sandbox Code Playgroud)

无论GCC和铛打印

1
1
Run Code Online (Sandbox Code Playgroud)

但另外clang发出以下警告:

prog.cc:3:13: warning: field 'j' is uninitialized when used here [-Wuninitialized]
    int i = j + 1;
            ^
prog.cc:8:7: note: in implicit default constructor for 'A' first required here
    A …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer

7
推荐指数
1
解决办法
200
查看次数