有了代码,我得到以下输出:
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;
}
答案 0 :(得分:10)
首先,您必须记住,除非reserve用于向量的内存,否则由于其容量需要增加,它需要分配和重新分配内存。
重新分配基本上会分配新的内存,然后将向量中的元素复制到新的内存中。
此外,当您将值推入向量时,该值需要复制到向量中。您可以通过emplacing的值(这意味着它是在向量中适当的位置)来避免的,或者通过moving的值push it back来避免这种情况。
答案 1 :(得分:5)
第一个副本已清除-push_back()需要复制对象。
在第二个副本中,发生了两件事: