Copy constructors and assignment operators

I wrote the following program to check when the copy constructor is called and when the assignment operator is called:

#include class Test { public: Test() : iItem (0) { std::cout << "This is the default ctor" << std::endl; } Test (const Test& t) : iItem (t.iItem) { std::cout << "This is the copy ctor" << std::endl; } ~Test() { std::cout << "This is the dtor" << std::endl; } const Test& operator=(const Test& t) { iItem = t.iItem; std::cout << "This is the assignment operator" << std::endl; return *this; } private: int iItem; }; int main() { { Test t1; Test t2 = t1; } { Test t1; Test t2 (t1); } { Test t1; Test t2; t2 = t1; } } 

This results in the following output (just added empy lines to make it more understandable):

  doronw@DW01 : ~ $ ./test
 This is the default ctor
 This is the copy ctor
 This is the dtor
 This is the dtor

 This is the default ctor
 This is the copy ctor
 This is the dtor
 This is the dtor

 This is the default ctor
 This is the default ctor
 This is the assignment operator
 This is the dtor
 This is the dtor


The second and third set behave as expected, but in the first set the copy constructor is called even though the assignment operator is used.

Is this behavior part of the C ++ standard or just a clever compiler optimization (I am using gcc 4.4.1)

+3
source share
3 answers

The first test case does not use an assignment operator. It simply uses an initialization form called “copy initialization”. When an object is initialized, code initialization does not consider explicit constructors.

 struct A { A(); // explicit copy constructor explicit A(A const&); // explicit constructor explicit A(int); // non-explicit "converting" constructor A(char const*c); }; A a; A b = a; // fail A b1(a); // succeeds, "direct initialization" A c = 1; // fail, no converting constructor found A d(1); // succeeds A e = "hello"; // succeeds, converting constructor used 

copy initialization is used in those cases that correspond to implicit conversions, where one is not an explicit Start conversion, as in the function of passing arguments and returning from the function.

+10
source

C ++ 8.5 / 12 standard

The initialization that occurs in the transfer of arguments, the return of the function, the exception (15.1), the handling of the exception (15.3) and the list of initializers enclosed in brackets (8.5.1) are called copy-initialization and are equivalent to the form

 T x = a; 

The initialization that occurs in new expressions (5.3.4), static_cast expressions (5.2.9), the type conversion function for notation types (5.2.3), and basic and element initializers (12.6.2) is called direct initialization and is equivalent to the form

 T x(a); 
+3
source

Your first set conforms to the C ++ standard, and not because of some optimization.

Section 12.8 ( [class.copy] ) of C ++ standard provides an example:

 class X { // ... public: X(int); X(const X&, int = 1); }; X a(1); // calls X(int); X b(a, 0); // calls X(const X&, int); X c = b; // calls X(const X&, int); 

The last line will match your case.

+2
source

Source: https://habr.com/ru/post/1412504/


All Articles