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
答案 0 :(得分:7)
您永远不会初始化Obj::val
,因此该值恰好是构建Obj
实例时在该内存位置发生的情况。
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 ),更改参数名称
在提议的解决方案中,标记为( 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) {}