简体   繁体   中英

Copy constructor vs assignment operator with STL vector

Having this class:

class A
{
    int number;
    int number2;
public:
    A(int _number):number(_number),number2(0)
    {
        cout<<"Normal constructor\n";
    }
    A()
    {
        cout<<"Default constructor\n";
    }

    A(const A& source)
    {
        number = source.number;
        number2 = source.number2;
        cout<<"Copy constructor\n";
    }

    A & operator=(const A& source)
    {
        number = source.number;
        number2 = source.number2;
        cout<<"Assignment operator\n";
        return *this;
    }
};

If vector<A> obj {1,2,3} is created, normal constructor is called three times because it is not declared as explicit and therefore it is used as a converting constructor . Then the copy constructor is called three times.

  • Is there any way a vector can be declared and instantiated while skipping the copying operation?

If vector<A> obj_1; is executed, an empty vector which can hold objects of type A is created - no constructors called , but the object exists .

  • Why there is no constructor called?
  • Did I declared the object such as it is fully workable?

From this link :

  1. A copy constructor is used to initialize a previously uninitialized object from some other object's data.

  2. An assignment operator is used to replace the data of a previously initialized object with some other object's data.


Doing obj_1 = obj , if my obj_1 was previously initialized results in calling the copy constructor instead of operator= function inside my class A as I was expecting?

Also, inside vector there is already an operator= function. How can I know when will be called each?

vector<A> obj {1,2,3};
vector<A> obj_1;
obj_1 = obj;  // Why copy constructor called instead of function operator= inside my class

Is there any way a vector can be declared and instantiated while skipping the copying operation?

No. When you do vector<A> obj {1,2,3} the compiler creates a std::initializer_list<A> from the values provided. That std::initializer_list creation is the reason you see the three normal constructor calls. The vector then has to copy those elements because the underlying storage for those elements is const . There is no was to get around that with list initialization. Even vector<A> obj {A(1),A(2),A(3)} would still cause copies.

If you don't want that then one thing you can do is create storage for the elements using reserve , and then use emplace_back to directly construct the objects in the vector like

vector<A> obj;
obj.reserve(3);
for (int i = 1; i < 4, ++i)
    obj.emplace_back(i);

Doing obj_1 = obj , if my obj_1 was previously initialized results in calling the copy constructor instead of operator= function inside my class A as I was expecting?

This is because obj_1 is empty. Since it is empty, there is no element to call the assignment operator on. Instead what it does is create elements in obj_1 that are copies of obj and the most efficient way to do that is to just call the copy constructor instead of default constructing the objects and then assigning to them.

If you had

vector<A> obj {1,2,3};
vector<A> obj_1 {3, 4, 5};
obj_1 = obj; 

Instead then you would see the assignment operator be used instead since there are objects to actually assign to.

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