我正在使用cpp.sh来编译和运行此代码。我期望number
的值可以默认初始化为0
或一些垃圾值。但是,在构造函数中,即使if
条件为false,number
的值仍会初始化为10
。有人可以向我解释发生了什么吗?
#include <iostream>
class Number
{
int number;
public:
Number(std::string s)
{
if (s == "foo")
{
number = 10;
}
}
int getNumber()
{
return number;
}
};
int main()
{
Number n("bar");
std::cout << n.getNumber() << std::endl;
}
答案 0 :(得分:11)
如果没有为对象指定初始值设定项,则默认初始化该对象。存储对象时 获得自动或动态存储持续时间,该对象具有不确定值,如果 没有对该对象执行初始化,该对象保留一个不确定的值,直到该值为止 取代
值10与编译器完成的优化一样,以消除条件语句。
答案 1 :(得分:4)
应初始化所有原始数据类型。在这里,您无需初始化即可访问int
。您可以在声明使用{}
时初始化变量。例如,请参阅下面的代码 -
class Number
{
int number {0}; // or any other default value.
};
请注意,访问未初始化的变量是未定义的行为。有关未定义行为的更多详细信息,您可以看到 - http://en.cppreference.com/w/cpp/language/ub
答案 2 :(得分:4)
这是构造函数的编译器优化。您可以检查它是否更改了优化级别。
由于未初始化数据成员number
,因此变量的值遵循UB规则。这就是说编译器(上面引用的cpp.sh)优化了Full(-O2)赋值总是10的构造函数,因为它比尝试进行字符串比较和跳转或赋值更便宜。
尝试将优化级别更改为normal
并且没有发生。
尝试VS 2017,调试&amp;释放,但它不会发生。
这是编译器完成的优化。特别是cpp.sh在Full (-o2)
答案 3 :(得分:3)
因此,在这个幸运的情况下,未定义的行为导致该数字被视为初始化为10(但实际上它不是!)。尝试使用它会在代码中产生更多的UB。
为避免此类问题,请始终使用某个值初始化变量。例如:
Number(std::string s)
: number ( -1 )
{
if (s == "foo")
{
number = 10;
}
}
答案 4 :(得分:2)
如果s不是"foo"
,则在构建Number
的实例时,您的代码会将数字取消初始化。然后,当您使用n.getNumber()
读取数字的值时,您将调用 undefined bahavior 。这意味着此函数返回的值可以是任何整数(包括您不希望的值10)。