简体   繁体   中英

Is Assignment Operator or Copy Constructor invoked for array/vector insertions?

Language: C++

My question is about whether the copy constructor or the assignment operator is called in the following situations. To precede, I understand the following:

MyClass a(3);      // single param constructor
MyClass b(a);      // copy constructor invoked
MyClass c = b;     // copy constructor invoked
MyClass d;         // default constructor
d = c;             // assignment operator invoked

However, I was hoping someone could give a similar breakdown for these:

1) For lines 2-3, is assignment operator or copy constructor called?

MyClass arr[10];
arr[2] = a;
arr[5] = MyClass(1);

2) Constructor, then copy constructor? Or constructor, then assignment operator?

MyClass arr2[] = {MyClass(), MyClass(9)};

3) Assuming vector v 's internal representation has space for one more object, is new element copied using assignment operator or copy constructor?

std::vector<MyClass> v;
v.push_back(MyClass(2));
...
...

4) Assuming vector v 's internal representation is out of space and must realloc, are old elements copied using assignment operator, or copy constructor?

v.push_back(MyClass(2)); // Assuming vector is out of space; must realloc
MyClass arr[10];

Constructor for MyClass is called 10 times, as 10 objects of arr are created.

arr[2] = a;

Assignment operator is invoked, assigns arr[2] to a .

arr[5] = MyClass(1);

First single param constructor with parameter 1 is called and creates an object of MyClass. Then assignment operator is invoked.

MyClass arr2[] = {MyClass(), MyClass(9)};

Two constructors and only are called here. First the Myclass() and then "single param constructor" MyClass(9) . The array declaration with initialization is not an assignment, cause no existing arrays members exists to assign to.

std::vector<MyClass> v;

Constructor for std::vector<MyClass> is called.

v.push_back(MyClass(2));

std::vector::push_back creates a copy of the class and stores it. So first MyClass(2) constructor is called, then copy constructor MyClass(const MyClass &) is called to copy the value. Then the copied object is stored.

Assuming vector v's internal representation is out of space and must realloc, are old elements copied using assignment operator, or copy constructor?

Copy operator is invoked for each member. So:

std::vector<MyClass> a;

Calls constructor for std::vector<MyClass>

a.push_back(MyClass(1));

Calls constructor for MyClass(1) and copies it using copy cosntructor MyClass(MyClass&) .
After that if we add another element to the array:

a.push_back(MyClass(2));

Then MyClass(2) constructor is called, then copy constructor is called for MyClass(MyClass&) for the just constructed MyClass(2) object. Then the vector copy-constructs all existing members from the ned, so for the pre-existing object in the vector MyClass(1) already upped copy constructor is called.

Really, play with it a little. And insert cout everywhere to see it:

struct MyClass {
    MyClass(int a = 0) : _a(a) {
        _count = count++;
        std::cout << __func__ << " " 
            << _count << " "
            << this << " "
            << this->_a << "\n";
    }
    MyClass(const MyClass &old_obj) {
        this->_a = old_obj._a;
        std::cout << __func__ << "Copy " 
            << _count << " "
            << this << " "
            << this->_a << " "
            << &old_obj << " "
            << old_obj._a << "\n";
    }
    void operator=(const MyClass &old_obj) {
        this->_a = old_obj._a;
        std::cout << "MyClass" << __func__ << " " 
            << _count << " "
            << this << " "
            << this->_a << " "
            << &old_obj << " "
            << old_obj._a << "\n";
    }
    static int count;
    int _count;
    int _a;
};

int MyClass::count = 0;

When you have

type variable_name = some_value

then you are declaring a variable and will always be calling its constructor (if it has one). This is called copy initialization and this will never be assignment

So, in

MyClass arr[10];      // 1
arr[2] = a;           // 2
arr[5] = MyClass(1);  // 3

Line 1 creates an array of 10 MyClass and default constructs each of them. Lines 2 and 3 are assignment.

In

MyClass arr2[] = {MyClass(), MyClass(9)};

You initialize an array of 2 objects using the values in the *braced-init-list` as the initializers for the array members. There are many rules governing list initialization but the one thing they have in common is no assignment will happen, only constructor calls.

With

std::vector<MyClass> v;
v.push_back(MyClass(2));

Assuming the vector doesn't reallocate, you have a constructor call for MyClass(2) and then the element in the vector is copy constructed from that temporary object. If the vector has to grow then all of the current elements are copy/move constructed to a new buffer then the temporary is copied constructed at the end.

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