尝试在构造函数中初始化数据成员,但它失败了.为什么?

Cof*_*ker 0 c++ struct instance-variables

结构指针的成员变量返回错误的数字.

这是结构声明:

struct Obj {
    int val;
    Obj(int val) { val = val; }
};
Run Code Online (Sandbox Code Playgroud)

这是它变得时髦的地方:

Obj* cool = new Obj(4);
cout << cool->val; // outputs a number that's not 4
cout << (cool->val == 4); // prints 0... interesting
Run Code Online (Sandbox Code Playgroud)

Fil*_*efp 7

为什么我得到这些奇怪的数字?

你永远不会初始化Obj::val,所以这个值恰好是构造一个实例的那个内存位置Obj.


理由:名字正在玩"捉迷藏"

struct Obj {
    int val;         // (A)
    Obj(int val) {   // (C)
      val = val;     // (B)
    }
};
Run Code Online (Sandbox Code Playgroud)

里面的构造函数Obj命名参数val是隐藏的数据成员命名val; 换句话说,就是将名为的参数的值赋给名为val的参数val.

标准说,在比前一个声明更窄的范围内声明的变量将有效地隐藏旧的.

这意味着由于val(B)处的参数比(A)的范围更窄,因此在(C)处编译器认为您指的是参数.


提出的解决方案

您有几种方法可以解决此问题

this->val = val;              // (A)
Obj::val  = val;              // equivalent
Run Code Online (Sandbox Code Playgroud)

Obj (int val) : val (val) { } // (B)
Run Code Online (Sandbox Code Playgroud)

Obj (int foo) { val = foo; }  // (C)
Run Code Online (Sandbox Code Playgroud)

  • A),用于this->val明确声明您要将值分配给Obj的数据成员

  • B),使用mem-initializer,Obj::val不会被参数名称隐藏

  • C),更改参数的名称


MEM-初始化看起来怪异,为什么它包括在内?

提议的解决方案中,标记为(B)的解决方案是首选解决方案.

它使用mem-initializer调用,并在调用构造函数时直接使用参数val的值初始化成员val ; 而不是首先必须默认初始化,然后分配一个值.

建议也不要使用与成员变量同名的参数,因为如果忘记了名称隐藏,它可能容易出错.

一种常见的设计是为每个数据成员添加前缀,m_以明确说明这些实际上是实例的成员,例如在以下代码段中:

struct Obj {
    Obj(int val) : m_val (val) { }
    int m_val;
};
Run Code Online (Sandbox Code Playgroud)