c++ push_back()和emplace_back()区别
一、区别:
都可以直接根据传入的参数选择匹配的构造函数隐式构造对象。
但隐式构造时:
1. push_back()
-
如果未定义移动构造函数,传入到push_back()的参数与元素对应类的某个构造函数匹配,那么会隐式构造一个元素,首先调用构造函数构造临时对象,然后调用拷贝构造函数讲这个临时对象放入容器中。
-
如果定义了移动构造函数,上述过程就会变成依次调用构造函数和移动构造函数。
2. emplace_back()
- 在容器尾部添加一个元素, 传入到emplace_back()的参数与元素对应类的某个构造函数匹配, 这个元素原地构造对象,仅需要调用构造函数, 而不会调用拷贝构造函数或移动构造函数。
3. 程序示例
#include <iostream>
#include <vector>
using namespace std;
class Foo{
private:
int a;
public:
Foo(int num): a(num) {
cout<<"Foo Constructor "<<a<<endl;
}
Foo(){
cout<<"Default Foo Constructor"<<endl;
}
~Foo() { cout << "Foo Destructor..." << endl; }
Foo(const Foo& a){
cout<<"copy constructor"<<endl;
}
Foo(const Foo&& a){
cout<<"move constructor"<<endl;
}
};
int main() {
cout<<endl<<"push_back:"<<endl<<endl;
vector<Foo> vec1;
vec1.push_back(1);
cout<<endl<<"emplace_back:"<<endl<<endl;
vector<Foo> vec2;
vec2.emplace_back(2);
vec2.emplace_back(3);
}
输出:
push_back:
Foo Constructor 1
move constructor //若注释掉移动构造函数,此处将调用拷贝构造函数
Foo Destructor...
emplace_back:
Foo Constructor 2
Foo Constructor 3
copy constructor //vec2扩容后,拷贝元素到新空间
Foo Destructor... //vec2扩容后,旧空间中的元素析构
Foo Destructor... //vec1中的元素析构
Foo Destructor... //vec2中的元素析构
Foo Destructor... //vec2中的元素析构
4. 疑问:为什么emplace_back:
后,打印了一次拷贝构造函数,以及四次析构函数?
https://blog.csdn.net/luomoshusheng/article/details/48226517
因为定义的vector初始容量为0,加入一个元素容量扩容为1,再加入一个元素,分配新空间扩容为2,vector中元素要拷贝到新空间,旧元素销毁。
二、相同之处
- 拷贝构造函数和移动构造函数均已定义,push_back/emplace_back向容器中加入左值元素,均将调用构造函数和拷贝构造函数拷贝对象加入到容器中。
#include <iostream>
#include <vector>
using namespace std;
class Foo{
private:
int a;
public:
Foo(int num): a(num) {
cout<<"Foo Constructor "<<a<<endl;
}
Foo(){
cout<<"Default Foo Constructor"<<a<<endl;
}
~Foo() { cout << "Foo Destructor..." <<endl; }
Foo(const Foo& foo){
cout<<"copy constructor"<<endl;
}
Foo(const Foo&& foo){
cout<<"move constructor"<<endl;
}
};
int main() {
cout<<endl<<"push_back:"<<endl<<endl;
vector<Foo> vec1;
Foo foo1(1);
vec1.push_back(foo1);
cout<<1<<endl;
cout<<endl<<"emplace_back:"<<endl<<endl;
vector<Foo> vec2;
Foo foo2(2);
vec2.emplace_back(foo2);
cout<<2<<endl;
}
push_back:
Foo Constructor 1
copy constructor
1
emplace_back:
Foo Constructor 2
copy constructor
2
Foo Destructor...
Foo Destructor...
Foo Destructor...
Foo Destructor...
- 拷贝构造函数和移动构造函数均定义,push_back/emplace_back向容器中加入显式构造的右值元素, 那么均会先后调用构造函数和移动构造函数,再加入到容器中。
#include <iostream>
#include <vector>
using namespace std;
class Foo{
private:
int a;
public:
Foo(int num): a(num) {
cout<<"Foo Constructor "<<a<<endl;
}
Foo(){
cout<<"Default Foo Constructor"<<a<<endl;
}
~Foo() { cout << "Foo Destructor..." <<endl; }
Foo(const Foo& foo){
cout<<"copy constructor"<<endl;
}
Foo(const Foo&& foo){
cout<<"move constructor"<<endl;
}
};
int main() {
cout<<endl<<"push_back:"<<endl<<endl;
vector<Foo> vec1;
vec1.push_back(Foo(1));
cout<<1<<endl;
cout<<endl<<"emplace_back:"<<endl<<endl;
vector<Foo> vec2;
vec2.emplace_back(Foo(2));
cout<<2<<endl;
}
push_back:
Foo Constructor 1
move constructor
Foo Destructor...
1
emplace_back:
Foo Constructor 2
move constructor
Foo Destructor...
2
Foo Destructor...
Foo Destructor...