vector::push_back和vector::emplace_back区别
emplace_back() 和 push_back() 功能上类似,但底层实现机制是不同的。push_back() 向容器尾部添加元素时,首先会创建这个元素(调用构造函数),然后再将这个元素拷贝或者移动到容器中(调用复制构造函数或者移动构造函数);而 emplace_back() 在实现时,则是直接在容器尾部创建这个元素,也就是只会调用一次构造函数。
简单实例
下面给出一个简单的例子:
#include <vector>
#include <iostream>
using namespace std;
class testDemo
{
public:
testDemo(int num):num(num){
std::cout << "call constructor function" << endl;
}
testDemo(const testDemo& other) :num(other.num) {
std::cout << "call copy constructor function" << endl;
}
testDemo(testDemo&& other) :num(other.num) {
std::cout << "call move constructor function" << endl;
}
private:
int num;
};
int main()
{
cout << "emplace_back:" << endl;
std::vector<testDemo> demo1;
demo1.emplace_back(2);
cout << "push_back:" << endl;
std::vector<testDemo> demo2;
demo2.push_back(2);
}
输出结果如下:
emplace_back:
call constructor function
push_back:
call constructor function
call move constructor function
可以看到push_back会调用构造函数和移动构造函数,而emplace_back只会调用构造函数,需要注意push_back在类有移动构造函数的时候会默认先调用移动构造函数,若没有移动构造函数才会调用复制构造函数,例如如果把移动构造函数去掉:
#include <vector>
#include <iostream>
using namespace std;
class testDemo
{
public:
testDemo(int num):num(num){
std::cout << "call constructor function" << endl;
}
testDemo(const testDemo& other) :num(other.num) {
std::cout << "call copy constructor function" << endl;
}
/*
testDemo(testDemo&& other) :num(other.num) {
std::cout << "call move constructor function" << endl;
}
*/
private:
int num;
};
int main()
{
cout << "emplace_back:" << endl;
std::vector<testDemo> demo1;
demo1.emplace_back(2);
cout << "push_back:" << endl;
std::vector<testDemo> demo2;
demo2.push_back(2);
}
输出结果如下:
emplace_back:
call constructor function
push_back:
call constructor function
call copy constructor function
一个更复杂实例
下面给一个更复杂的实例:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
using namespace std;
class Str{
public:
char *str;
int id;
Str(const char value[], const int id)
{
cout<<"origin construct function..."<< value <<endl;
str = NULL;
int len = strlen(value);
str = new char[len + 1];
memset(str,0,len + 1);
strcpy(str,value);
this->id = id;
}
Str(const Str &s)
{
cout<<"copy construct function..." << s.str<<endl;
str = NULL;
int len = strlen(s.str);
str = new char[len + 1];
memset(str,0,len + 1);
strcpy(str,s.str);
this->id = s.id;
}
Str(Str &&s)
{
cout<<"move construct function..."<<endl;
str = s.str;
id = s.id;
s.str = NULL;
}
~Str()
{
if(str != NULL)
{
cout<<"destruct funciton..." <<str<<endl;
delete []str;
str = NULL;
}
}
};
int main()
{
vector<Str> strVec;
vector<Str> strVec1;
cout<<"********push_back****************"<<endl;
strVec.push_back(Str("abc",123));
cout<<"********emplace_back****************"<<endl;
strVec1.emplace_back("def",345);
cout<<"********finish****************"<<endl;
return 0;
}
输出结果如下:
********push_back****************
origin construct function...abc
move construct function...
********emplace_back****************
origin construct function...def
********finish****************
destruct funciton...def
destruct funciton...abc
可以看到,emplace_back支持直接传入构造函数的参数来构造创建元素,而push_back必须先构造元素,再通过复制构造函数传入。