push_back到std :: vector,复制构造函数被重复调用

时间:2018-08-31 06:19:12

标签: c++

有了代码,我得到以下输出:

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

在调试代码时,对于3个测试用例,我发现复制构造函数的第一个调用是相同的(并且我认为这是有道理的):制作对象的副本并将其推入向量。

但是,通过“ _Umove_if_noexcept”对复制构造函数进行了其他调用。

对于测试2,当vec已经具有一个条目时,它将进一步调用复制构造函数的一次。

对于测试3,当vec已经具有两个条目时,它将进一步调用复制构造函数的两次。

在Visual Studio 2017和gcc 5.4.0上可重现。

为什么会这样? 有性能问题吗?

谢谢

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

2 个答案:

答案 0 :(得分:10)

首先,您必须记住,除非reserve用于向量的内存,否则由于其容量需要增加,它需要分配和重新分配内存。

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

此外,当您将值推入向量时,该值需要复制到向量中。您可以通过emplacing的值(这意味着它是在向量中适当的位置)来避免的,或者通过moving的值push it back来避免这种情况。

答案 1 :(得分:5)

第一个副本已清除-push_back()需要复制对象。

在第二个副本中,发生了两件事:

  1. 首先,由于向量没有足够的空间,因此需要扩展,并且在该操作期间,它需要复制所有存储的对象
  2. 第二秒,对象被复制