Reputation: 675
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
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
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
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
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
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