C ++使用字符串比较的奇怪行为

时间:2018-02-14 08:38:07

标签: c++ string

我正在使用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;
}

5 个答案:

答案 0 :(得分:11)

来自[dcl.decl]

的第9条
  

如果没有为对象指定初始值设定项,则默认初始化该对象。存储对象时   获得自动或动态存储持续时间,该对象具有不确定值,如果   没有对该对象执行初始化,该对象保留一个不确定的值,直到该值为止   取代

值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)。