Abdulrahman Alhemeiri
Abdulrahman Alhemeiri

Reputation: 675

C++ Weird behavior with String comparison

I am using cpp.sh to compile and run this code. I am expecting the value of number to be either default initialized to 0 or some garbage value. However, in the constructor, even though the if condition is false, the value of number is still initialized to 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;
}

Upvotes: 7

Views: 341

Answers (5)

Yola
Yola

Reputation: 19093

From clause 9 in [dcl.decl]

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.

Upvotes: 12

Stefano Buora
Stefano Buora

Reputation: 1062

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. 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.

Tried to change the optimization level to normal and it didn't happen.

Tried with VS 2017, debug & release and it doesn't happen.

It's an optimization done by the compiler. Specifically by the compiler used by cpp.sh at Full (-o2)

Upvotes: 5

Naseef Chowdhury
Naseef Chowdhury

Reputation: 2464

All the primitive data types should be initialized. Here you are accessing an int without initializing. 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

Upvotes: 3

Ivaylo Strandjev
Ivaylo Strandjev

Reputation: 71009

In case s is not "foo" your code leaves number uninitialized when constructing an instance of Number. Then when you read the value of number using n.getNumber() you invoke 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).

Upvotes: 2

Nikita Smirnov
Nikita Smirnov

Reputation: 872

So, in this lucky case undefined behavior causes that number is treated as initialized by 10 (but actually it is not!). Trying to use this will cause more UB in your code.

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

Upvotes: 3

Related Questions