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

时间:2014-06-06 21:22:12

标签: c++ struct instance-variables

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

这是结构声明:

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

2 个答案:

答案 0 :(得分:7)

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

您永远不会初始化Obj::val,因此该值恰好是构建Obj实例时在该内存位置发生的情况。


原因:名字正在播放“hide&amp; seek”

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

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

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

这意味着,因为( B )处的参数val的范围比( 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-initializer ,其中Obj::val不会被参数名称隐藏

  • C ),更改参数名称


mem-initializer 看起来很怪异,为什么会包含它?

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

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

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

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

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

答案 1 :(得分:2)

此:

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) {}