简体   繁体   English

C ++使用String比较的奇怪行为

[英]C++ Weird behavior with String comparison

I am using cpp.sh to compile and run this code. 我正在使用cpp.sh来编译和运行此代码。 I am expecting the value of number to be either default initialized to 0 or some garbage value. 我期望number的值可以默认初始化为0或一些垃圾值。 However, in the constructor, even though the if condition is false, the value of number is still initialized to 10 . 但是,在构造函数中,即使if条件为false, number的值仍会初始化为10 Can someone explain to me what's happening? 有人可以向我解释发生了什么吗?

#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;
}

From clause 9 in [dcl.decl] 摘自[dcl.decl]第9条

If no initializer is specified for an object, the object is default-initialized. 如果没有为对象指定初始化程序,则默认初始化该对象。 When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value , and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced 当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定的值 ,并且如果没有对该对象执行初始化,则该对象保留不确定的值,直到该值被替换为止。

Value 10 is placed just as optimization done by compiler to eliminate conditional statement. 值10与编译器完成的优化一样,以消除条件语句。

All the primitive data types should be initialized. 应初始化所有原始数据类型。 Here you are accessing an int without initializing. 在这里,您无需初始化即可访问int You can initialize the variable while declaring using {} . 您可以在声明使用{}时初始化变量。 For example, see below code - 例如,见下面的代码 -

class Number
{
    int number {0}; // or any other default value.
};

Please note that accessing uninitialized variable is Undefined Behavior . 请注意,访问未初始化的变量是未定义的行为 For more details regarding Undefined Behavior, you can see this - http://en.cppreference.com/w/cpp/language/ub 有关未定义行为的更多详细信息,您可以看到 - http://en.cppreference.com/w/cpp/language/ub

It's a compiler optimization on the constructor. 它是构造函数的编译器优化。 You can check it changing the optimization level. 您可以检查它是否更改优化级别。

As the data member number is not initialized, the value of the variable is following the UB rule. 由于未初始化数据成员number ,因此变量的值遵循UB规则。 That said the compiler (cpp.sh cited above) optimize the constructor at Full (-O2) assigning always 10, as it's times cheaper than trying to do the string comparison and make a jump or an assignment. 这就是说编译器(上面引用的cpp.sh)优化了Full(-O2)的构造函数,总是分配10,因为它比尝试进行字符串比较和跳转或赋值更便宜。

Tried to change the optimization level to normal and it didn't happen. 试图将优化级别更改为normal ,但没有发生。

Tried with VS 2017, debug & release and it doesn't happen. 尝试VS 2017,调试和发布,它不会发生。

It's an optimization done by the compiler. 这是编译器完成的优化。 Specifically by the compiler used by cpp.sh at Full (-o2) 特别是cpp.sh在Full (-o2)使用的编译器

So, in this lucky case undefined behavior causes that number is treated as initialized by 10 (but actually it is not!). 因此,在这个幸运的情况下,未定义的行为导致该数字被视为初始化为10(但实际上它不是!)。 Trying to use this will cause more UB in your code. 尝试使用它会在代码中产生更多UB。

To avoid such problems, prefer to always initialize a variable with some value. 为避免此类问题,请始终使用某个值初始化变量。 For example: 例如:

Number(std::string s)
    : number ( -1 )
{
    if (s == "foo")
    {
        number = 10;
    }
}

In case s is not "foo" your code leaves number uninitialized when constructing an instance of Number . 如果s不是"foo"在构造Number实例时,代码会保留未初始化Number Then when you read the value of number using n.getNumber() you invoke undefined bahavior . 然后,当您使用n.getNumber()读取number的值时,您将调用undefined bahavior This means the value of returned by this function can be any integer number (including by chance the value 10 that you don't expect). 这意味着此函数返回的值可以是任何整数(包括您不期望的值10)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM