我知道这个问题被问了很多,我看过很多引用"emplace_back构造就地,push_back()构造和复制“的解释。一些帖子询问为什么emplace_back调用复制构造函数,因为它们没有为向量保留内存。
但是对于下面的例子,我不知道emplace_back()比push_back()实现的更多。有人回答说“你需要为emplace_back()实现一个移动构造函数才能工作”,但是push_back()也可以利用这个移动构造函数。那么有什么不同呢?
#include <iostream>
#include <vector>
using namespace std;
class Int{
public:
int* p;
Int(int x): p(new int(x)) {cout<<"constructor called for "<<*p<<endl;}
Int(const Int& x): p(new int(*(x.p))) {cout<<"copy constructor called for "<<*p<<endl;}
~Int(){
if (p!= nullptr) {cout<<"destructor called for "<<*p<<endl;}
else{cout<<"destructor called for null ptr"<<endl;}
delete p;
}
Int(Int&& x): p(x.p) {
x.p = nullptr;
cout<<"move constructor called for "<<*p<<endl; // move constructor, remove to test emplace_back()
}
};
int main(){
vector<Int> v;
v.reserve(1);
v.emplace_back(Int(1)); // can switch to push_back()
// v.push_back(Int(1));
cout<<"end program"<<endl;
}对我来说,这两种方法似乎都调用复制构造函数而不调用移动构造函数,如果有移动构造函数,则调用移动构造函数。
发布于 2021-08-08 07:31:56
emplace_back通过将参数转发到元素类型的构造函数来就地构造元素,因此您可以
v.emplace_back(1); // forwarding 1 to Int::Int(int) to construct the element directlypush_back总是需要一个元素,即一个Int。当您将1作为v.push_back(1);传递给它时,会发生隐式转换。(Int::Int(int)从1构造一个临时Int,然后将其传递给push_back,随后Int的move构造函数从临时构造元素构造该元素。即比v.emplace_back(1);多一次移动构造函数调用。
您还可以将Int传递给像v.emplace_back(Int(1));这样的emplace_back,如上所述,临时Int被转发到Int的move构造函数来构造元素,该构造函数的作用与v.push_back(Int(1));相同。
正如@JeJo所建议的,emplace_back和push_back之间有另一个区别,因为C++17。emplace_back返回对插入元素的引用,而push_back不返回任何内容。
https://stackoverflow.com/questions/68698641
复制相似问题