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

Trying to initialize a data-member in the constructor, but it fails. Why?

本文关键字:失败 为什么 数据成员 初始化 构造函数      更新时间:2023-10-16

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

下面是结构体声明:

struct Obj {
    int val;
    Obj(int val) { val = val; }
};

这里是它变得时髦的地方:

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

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

您从未初始化Obj::val,因此该值就是在构建Obj实例时恰好在该内存位置上的值。


原因:名字在播放"hide &seek&quot;

struct Obj {
    int val;         // (A)
    Obj(int val) {   // (C)
      val = val;     // (B)
    }
};

Obj的构造函数中,名为val的参数隐藏了名为val数据成员;换句话说,你是在将名为val的实参的值赋给名为val的实参。

这意味着由于参数val at (B)的范围比( a )更窄,因此在(C)点,编译器认为您引用的是参数。


提出解决方案

你有几个选择来解决这个问题

this->val = val;              // (A)
Obj::val  = val;              // equivalent

<一口>

Obj (int val) : val (val) { } // (B)

<一口>

Obj (int foo) { val = foo; }  // (C)

<一口>

  • A),使用this->val显式声明您希望将值赋给Obj

    的数据成员
  • B),使用mem-初始化器,其中Obj::val不会被参数名称

    隐藏
  • C),更改参数的名称


mem初始化器看起来很怪异,为什么要包含它?

Proposed Solutions中,标记为(B)的方案为首选方案。

使用mem初始化式调用,并在调用构造函数时直接使用实参val的值初始化成员val;而不是先默认初始化,然后赋值。

还建议不要使用与成员变量同名的参数,因为如果忘记了名称隐藏,则容易出错。

一种常见的设计是在每个数据成员前缀m_,以显式地声明它确实是实例的成员,如下面的代码片段:
struct Obj {
    Obj(int val) : m_val (val) { }
    int m_val;
};

This:

Obj(int val) { val = val; }

只是将形参赋值给自身,并留下包含垃圾的成员变量。你需要:

Obj(int val) : val(val) {}

或者(如果你真的需要赋值而不是初始化):

Obj(int val) { this->val = val; }

或:

Obj(int the_val) { val = the_val; }

可以考虑对成员使用命名约定:

int m_val;
Obj(int val) : m_val(val) {}