首页 > 解决方案 > push_back to std::vector, the copy constructor is repeatedly called

问题描述

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;
}

标签: c++

解决方案


首先,您必须记住,除非您为向量保留内存,否则它需要分配和重新分配内存,因为它的容量需要增加。

重新分配基本上是分配新内存,然后将向量中的元素复制到新内存。

此外,当您将值推入向量时,需要将该值复制到向量中。您可以通过放置值来避免这种情况(这意味着它是在向量中就地构造的),或者在您将其推回时移动该值。


推荐阅读