2

所以我正在努力理解 C++ 中的初始化规则。

我写了以下代码:

struct B {
  int i;

  // this prevents the definition of an implicit default constructor
  B( int j ) : i(j) {}

};

struct C {
  int i;

  // i is not mentioned in the initializer list
  // the compiler will call default constructor for i
  C() {}

};


int main() {

  int x( 1 );
  cout << " x = " << x << endl;

  // error: no matching function for call to ‘B::B()’
  //B b4 = B();
  //cout << " b4.i = " << b4.i << endl;

  C c1;
  cout << " c1.i = " << c1.i << endl;
}

1) x 已正确初始化为 1,但我不理解符号“int x(1)”。它不是值初始化的(我们会写“int x = int()”,然后 x 将为 0)。它也不是构造函数调用,因为内置类型没有构造函数。此外,以下页面明确指出:“只有具有构造函数的类的对象才能使用函数式语法进行初始化”。

http://msdn.microsoft.com/en-us/library/w7wd1177(v=vs.100).aspx

2) 如果我取消注释 b4 的创建,它将无法编译。因为我定义了一个构造函数,所以编译器不会生成一个隐式的默认构造函数。这可以。但是为什么这会阻止使用“B()”创建一个临时的值初始化对象呢?写“B()”绝不是构造函数调用,是吗?

3) 正如 C 类的注释中所解释的,初始化列表中没有提到 i。因此,它应该是默认初始化的,这意味着对于 int 类型未定义。但是每次我运行程序时输出都是“c1.i = 0”。

谢谢。

4

3 回答 3

3
  1. int x(1);int x = 1;与为内置类型编写相同。

  2. 对于具有用户定义的构造函数(非聚合)的类型,编写T() 总是调用默认构造函数;这就是代码无法编译的原因。

  3. c1.i确实是未初始化的,读取它是未定义的行为。您的编译器可能会将内存归零,尤其是在您没有启用优化的情况下;或者只是偶然打印出零。你当然不能指望这种行为。这是clang打印垃圾的输出。

于 2013-07-18T02:59:28.387 回答
2
  1. 这种表示法int x(1);称为直接初始化。它是为原生类型和类分别定义的。在后一种情况下,将调用构造函数。

  2. 在这种情况下,如果没有默认构造函数,就没有值初始化之类的东西。构造临时对象的规则与构造命名对象的规则相同。

  3. 读取未初始化的值会产生未定义的行为。再次运行相同的程序可能总是产生相同的结果,但尝试其他程序、其他机器、其他平台可能(或可能不会)发生其他事情。未定义的字面意思是标准未定义,不会崩溃或随机或产生错误消息。

    对于只依赖最佳可用规范保证的人(包括所有聪明人),具有未定义行为的程序是不正确的,并且可以假定它在您最不期望的时候崩溃。

于 2013-07-18T03:01:41.330 回答
0

如果在调试模式下运行程序,它会显示:

c1.i = -858993460

这是“CCCCC...CC”的值,这是C++调试模式下未初始化值的默认值。

于 2014-11-10T14:55:04.437 回答