Reputation: 15239
could someone explain what happens in this code:
example here: https://ideone.com/1cFb4N
#include <iostream>
using namespace std;
class toto
{
public:
bool b;
toto(bool x)
{
cout<< "constructor bool:" << (x ? "true": "false")<<endl;
b = x;
}
~toto() {}
};
int main()
{
toto t = new toto(0);
cout << "t.b is " << (t.b ? "true": "false")<<endl;
t = new toto(false);
cout << "t.b is " << (t.b ? "true": "false")<<endl;
return 0;
}
output:
constructor bool:false
constructor bool:true
t.b is true
constructor bool:false
constructor bool:true
t.b is true
Upvotes: 43
Views: 5712
Reputation: 310990
In this declaration
toto t = new toto(0);
the object t
of the class type toto
is initialized by the pointer returned by the expression new toto(0)
. As the returned pointer is not equal to nullptr
then it is implicitly converted to the boolean value true.
So in fact you have
toto t = true;
except that there is a memory leak because the address of the allocated object is lost. So the allocated object can not be deleted.
You could imagine the declaration above the following way.
toto *ptr = new toto(0)
toto t = ptr;
So the first line of this output
constructor bool:false
constructor bool:true
corresponds to the dynamically created object with the argument 0
new toto(0)
Then the returned pointer is used as an initializer and is implicitly converted to the boolean value true
that is used to initialize the declared object t
. So the second line shows the call of the conversion constructor (constructor with a parameter) with the value true.
There is no great difference between the above declaration and this assignment statement
t = new toto(false);
because again a pointer is used in the right hand of the assignment.
So the implicitly defined copy assignment operator converts the value of the pointer that is not equal to nullptr
to the boolean value true
.
This assignment you may imagine the following way
toto *ptr = new toto(false);
t = toto( ptr );
And again there is a memory leak.
From the C++ 14 Standard (4.12 Boolean conversions)
1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. For direct-initialization (8.5), a prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.
Upvotes: 77
Reputation: 36399
Any integer value is implicitly convertible to bool
, with 0 converting to false
, and all other values converting to true
.
The same applies to pointers, with null pointers converting to false
, and all others converting to true
.
toto t = new toto(0);
is equivalent to:
// Create new toto instance, convert 0 to false and assign to p
toto* p = new toto(0);
// Create toto instance on the stack and convert non-null pointer p to true
toto t = toto(p);
You can prevent these surprising conversions by marking single argument constructors as explicit
, meaning they won't be allowed to be considered during implicit conversions:
class toto
{
public:
bool b;
explicit toto(bool x)
{
cout<< "constructor bool:" << (x ? "true": "false")<<endl;
b = x;
}
~toto() {}
};
Upvotes: 20
Reputation: 60228
In this statement:
toto t = new toto(0);
in the expression new toto(0)
you are allocating a toto
with a default argument 0
. This int
can be implicitly converted to the bool
value false
, and this calls the bool
constructor, resulting in the output:
constructor bool:false
Then you are doing the assignment:
toto t = /* pointer returned by new */;
This pointer can be implicitly converted to bool
, and since this pointer is not nullptr
, it has a non-zero value. This combined with the fact that the toto
constructor accepting a bool
is not explicit
means that the constructor from bool
is called for t
, resulting in:
constructor bool:true
and this makes the b
member of t
have the value true
, and hence the next line of code results in the output:
t.b is true
Upvotes: 19