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.