尝试在构造函数中初始化数据成员,但失败.为什么
Trying to initialize a data-member in the constructor, but it fails. Why?
结构指针的成员变量返回错误的数字。
下面是结构体声明:
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"
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
显式声明您希望将值赋给ObjB),使用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) {}
相关文章:
- 为什么使用 P/Invoke 调用 dll 时,某些计算机中的 LoadLibrary 失败?
- VS2017,C++包含目录与附加包含目录,子文件夹包含失败-但为什么
- 为什么除非添加括号,否则构造函数上的模板替换会失败?
- 当给定默认值时,为什么此模板参数推导失败
- 为什么在使用typedef时类推导指南会失败
- 为什么 KMS drmModeSetCrtc() 在 X11 会话中运行时会失败并被拒绝权限?
- 如果我重新定义 sqrt 函数,为什么使用 std::sqrt 失败?
- 为什么模板参数推导失败?
- 为什么此对箭头 (->) 运算符的调用失败?
- 使用"std::function"和先前推断的模板参数替换失败 - 为什么?
- MSVS2010 C 控制台代码移植到MSVS2010 C GUI失败.为什么
- C++全局对象初始化失败——为什么?以及是否可以将对象放入.DATA部分
- RAII 失败 - 为什么此C++代码泄漏?- 在尝试块中加入 CTOR 阻止 DTOR
- 自动键入到自动方法失败.为什么
- C++模板参数推断失败.为什么
- c++对象的位拷贝失败?为什么
- 代码意外编译失败.为什么
- 尝试在构造函数中初始化数据成员,但失败.为什么
- 由于ECHILD错误,C++中的system()函数在一段时间内运行良好,但在返回-1时失败.为什么?
- BOOST/CSTDINT类型BOOST稀疏向量数组失败,为什么