Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

push_back to std::vector, the copy constructor is repeatedly called [duplicate]

Tags:

c++

With is code, I've got the following output:

A::A() is called
test #1
A::A(const A & other) is called
test #2
A::A(const A & other) is called
A::A(const A & other) is called
test #3
A::A(const A & other) is called
A::A(const A & other) is called
A::A(const A & other) is called

When debugging the code, for the 3 test cases, I found that the 1st invocation to copy constructor is the same (and I think it makes sense): make a copy of the object and push to the vector.

However, additional invocation to the copy constructor is made through "_Umove_if_noexcept".

For test #2, when vec already has ONE entry, it will further invoke ONE time of the copy constructor.

For test #3, when vec already has TWO entry, it will further invoke TWO times of the copy constructor.

This is reproducible on Visual Studio 2017 and gcc 5.4.0.

Why is this happening? Is there a performance issue?

Thanks

#include <iostream>
#include <vector>
class A
{
public:
    //constructor
    A()
    {
        a = 10;
        std::cout << "A::A() is called" << std::endl;
    }

    //copy constructor
    A(const A& other) : a(other.a)
    {
        std::cout << "A::A(const A & other) is called" << std::endl;
    }

    //assignment operator
    A& operator=(const A& other)
    {
        std::cout << "A::operator=(const A & other) is called" << std::endl;
        a = other.a;
        return *this;
    }
public:
    int a;
};

int main()
{
    std::vector<A> vec;
    //A::A() is called
    A a;

    std::cout << "test #1" << std::endl;
    //A::A(const A & other) is called by push_back
    vec.push_back(a);

    std::cout << "test #2" << std::endl;
    //A::A(const A & other) is called 
    //A::A(const A & other) is called from _Umove_if_noexcept
    vec.push_back(a);

    std::cout << "test #3" << std::endl;
    //A::A(const A & other) is called
    //A::A(const A & other) is called from _Umove_if_noexcept
    //A::A(const A & other) is called from _Umove_if_noexcept
    vec.push_back(a);   

     std::cin.get();

    return 0;
}
like image 314
milesma Avatar asked Aug 31 '18 06:08

milesma


People also ask

What does the std::vector Push_back () method do?

vector::push_back() push_back() function is used to push elements into a vector from the back. The new value is inserted into the vector at the end, after the current last element and the container size is increased by 1.

Does vector Push_back make a copy?

Yes, std::vector<T>::push_back() creates a copy of the argument and stores it in the vector.

How many times is copy constructor called?

You call the function by value and do two copies inside.

What does Push_back mean in C++?

C++ push_back() is a pre-defined function that is used to insert data or elements at the end of the vector or it pushes the element in the vector from the back.


2 Answers

First of all you have to remember that unless you reserve memory for the vector, it needs to allocate and reallocate memory as its capacity needs to increase.

The reallocation basically allocates new memory, then copies the element in the vector to the new memory.

Furthermore, when you push a value into a vector, that value needs to be copied into the vector. You can avoid that by emplacing the value (which means it's constructed in place in the vector), or by moving the value when you push it back.

like image 63
Some programmer dude Avatar answered Nov 14 '22 22:11

Some programmer dude


The first copy is clear - the push_back() needs to copy the object.

In the second copy, two things happen:

  1. first, because the vector doesn't contain enough space, it needs to expand, and during that operation, it needs to copy all stored objects
  2. second, the object is copied
like image 24
BЈовић Avatar answered Nov 14 '22 22:11

BЈовић