简体   繁体   中英

Copy constructors and Assignment Operators

I wrote the following program to test 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 behaviour part of the C++ standard or just a clever compiler optimization (I am using gcc 4.4.1)

No assignment operator is used in the first test-case. It just uses the initialization form called "copy initialization". Copy initialization does not consider explicit constructors when initializing the object.

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 does not explicitly kick off a conversion, as in function argument passing, and returning from a function.

C++ standard 8.5/12

The initialization that occurs in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and brace-enclosed initializer lists (8.5.1) is called copy-initialization and is equivalent to the form

 T x = a; 

The initialization that occurs in new expressions (5.3.4), static_cast expressions (5.2.9), functional notation type conversions (5.2.3), and base and member initializers (12.6.2) is called direct-initialization and is equivalent to the form

 T x(a); 

Your first set is according to the C++ standard, and not due to some optimization.

Section 12.8 ( [class.copy] ) of the C++ standard gives a similar 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 would be the one matching your case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM