C++ push_back和emplace_back的区别(含测试代码)
#include<iostream> #include<string> #include<set> #include<time.h> #include<cstring> #include <vector> #define LL long long #define MAXN 100010 using namespace std; int tot=0; class A { private: int lima; int limb; int las=tot; public: A(){las=++tot;lima = 1;limb =12 ;cout<<las<<" A created;"<<endl;} //explicit A(int a,int b):lima(a),limb(b){las=++tot;cout<<las<<" A common created"<<endl;} 会使得参数列表失效 A(int a,int b):lima(a),limb(b){las=++tot;cout<<las<<" A common created"<<endl;} A(A&& a){las=++tot;lima = a.lima; limb = a.limb;cout<<las<<" A move created"<<endl;} A(const A& a){las=++tot;lima = a.lima;limb = a.limb; cout<<las<<" A copy created"<<endl;} ~A(){cout<<las<<" A deleted"<<endl;}; }; inline A liss(int lim1,int lim2) { A limp(lim1,lim2); return limp; } vector<A>vec; int main() { //A lim(12,15); vec.reserve(20); /*把这个打开,防止扩容机制造成的拷贝构造结果混乱*/ //vec.push_back(lim); //vec.emplace_back(lim); //cout<<"where delete?"<<endl; /*观察结果:过程相同,都调用拷贝构造函数直接深拷贝构造,原因:传入参数都为左值*/ //vec.push_back(A(lim)); //vec.emplace_back(A(lim)); //cout<<"where delete?"<<endl; /*观察结果:过程一样,都产生临时变量并且调用移动构造函数,和网上说的不一样,推测函数返回值可能有问题,以下再次验证*/ //vec.push_back(liss(125,133)); //vec.emplace_back(liss(125,153)); //cout<<"where delete?"<<endl; /*观察结果:过程一样,都产生临时变量并且调用移动构造函数,和网上说的不一样,查询原码发现,部分编译器对于单个右值返回,pushback会使用右值引用接住后再次使用move转为右值并调用emplaceback*/ //vec.push_back({158,957}); //vec.emplace_back(158,957); //cout<<"where delete?"<<endl; /*观察结果: 1 A common created 2 A move created 1 A deleted 3 A common created where delete? 2 A deleted 3 A deleted 这就意味着对于传入右值参数的情况,push_back会先直接构造一个类,然后调用移动构造函数将类移动到vec末尾 而emplace_back会直接在末尾构造这个类 注意有的编译器会产生优化,单个右值传入的情况编译器会直接优化为emplaceback执行 而参数列表能够明显的看出区别,和网上所说一致,实验成功 */ //int a1=147,b1=254; //vec.push_back({a1,b1}); //vec.emplace_back(a1,b1); //cout<<"where delete?"<<endl; /*观察结果: 1 A common created 2 A move created 1 A deleted 3 A common created where delete? 2 A deleted 3 A deleted 这就意味着对于传入左值参数的情况,和上面是一样的 */ return 0; }