C++ copy-construct construct-and-assign question
- by Andy
Blockquote
Here is an extract from item 56 of the book "C++ Gotchas":
It's not uncommon to see a simple
initialization of a Y object written
any of three different ways, as if
they were equivalent.
Y a( 1066 );
Y b = Y(1066);
Y c = 1066;
In point of fact, all three of these
initializations will probably result
in the same object code being
generated, but they're not equivalent.
The initialization of a is known as a
direct initialization, and it does
precisely what one might expect. The
initialization is accomplished through
a direct invocation of Y::Y(int).
The initializations of b and c are
more complex. In fact, they're too
complex. These are both copy
initializations. In the case of the
initialization of b, we're requesting
the creation of an anonymous temporary
of type Y, initialized with the value
1066. We then use this anonymous temporary as a parameter to the copy
constructor for class Y to initialize
b. Finally, we call the destructor for
the anonymous temporary.
To test this, I did a simple class with a data member (program attached at the end) and the results were surprising. It seems that for the case of b, the object was constructed by the copy constructor rather than as suggested in the book.
Does anybody know if the language standard has changed or is this simply an optimisation feature of the compiler? I was using Visual Studio 2008.
Code sample:
#include <iostream>
class Widget
{
std::string name;
public:
// Constructor
Widget(std::string n) { name=n; std::cout << "Constructing Widget " << this->name << std::endl; }
// Copy constructor
Widget (const Widget& rhs) { std::cout << "Copy constructing Widget from " << rhs.name << std::endl; }
// Assignment operator
Widget& operator=(const Widget& rhs) { std::cout << "Assigning Widget from " << rhs.name << " to " << this->name << std::endl; return *this; }
};
int main(void)
{
// construct
Widget a("a");
// copy construct
Widget b(a);
// construct and assign
Widget c("c");
c = a;
// copy construct!
Widget d = a;
// construct!
Widget e = "e";
// construct and assign
Widget f = Widget("f");
return 0;
}
Output:
Constructing Widget a
Copy constructing Widget from a
Constructing Widget c
Assigning Widget from a to c
Copy constructing Widget from a
Constructing Widget e
Constructing Widget f
Copy constructing Widget from f
I was most surprised by the results of constructing d and e.