根据 《C++ Primer 5-th》P308 的解释,push_back() 是拷贝对象,而 emplace_back() 是构造对象
emplace_back() 直接在 容器中构造对象的方式 性能更优,可以减少内存拷贝
class T
{
int a = 1;
int b = 2;
string s;
public:
T() { cout << "默认构造函数" << endl; }; // 默认构造函数
T(int _a , int _b = 200, string _s = "good") :a(_a), b(_b), s(_s) { cout << "构造函数1" << endl; };
T(string _s) :s(_s) { cout << "构造函数2" << endl; }
T(const T& t) :a(t.a), b(t.b), s(t.s) { cout << "拷贝构造" << endl; }
void show()
{
cout << "a = " << a << '\t' << "b = " << b << "\t" << "s = " << s << endl;
}
};
设计好几个构造函数和一个拷贝构造函数进行测试
创建容器 vector,提前预留足够空间
注意一定要先 预申请足够的空间, 否则空间不够时, vector 就会重新申请空间, 然后 转移元素, 转移的时候元素在新旧空间之间发生拷贝, 这就会调用 拷贝构造函数, 从而影响这里 emplace_back 和 push_back 的判断
vector 内存大小管理
vector<T> test;
test.reserve(10);
T t1(10, 20, "t1"); // 构造函数1
test.push_back(t1); // 拷贝构造
test.push_back(1, 2, "t2"); // 报错, 必须传入类对象
test.push_back(T(1, 2, "t2")); // 构造函数1 拷贝构造
test.push_back(T("t3")); // 构造函数2 拷贝构造
可以看到,push_back 必须传入类的对象
,也就是先创建对象(占用内存),然后把这个对象 拷贝 到容器空间中
test.emplace_back(100, 200, "t3"); // 构造函数1
test.emplace_back("t4"); // 构造函数2
test.emplace_back(); //默认构造函数
emplace_back 不需要类的对象
,直接在容器空间中创建对象,节省了空间,而且少一次拷贝
test.emplace_back(T(100, 200, "t3")); // 构造函数1 拷贝构造
test.emplace_back(T("t4")); // 构造函数2 拷贝构造
T tt(10, 20, "tt"); // 构造函数1
test.emplace_back(tt); // 拷贝构造
测试发现,emplace_back 也可以传入 类对象,但是此时就会退化成 push_back()
int main()
{
vector<T> test;
test.reserve(10);
// 注意一定要先 预申请足够的空间, 否则空间不够时, vector 就会重新申请空间, 然后 转移元素, 转移的时候会发生元素在新旧空间的拷贝, 这会调用 拷贝构造函数, 影响这里 emplace_back 和 push_back 的判断
T t1(10, 20, "t1"); // 构造函数1
cout << endl;
cout << "########### 测试 push_back ###########" << endl << endl;
test.push_back(t1); // 拷贝构造
cout << endl;
test.push_back(T(1, 2, "t2")); // 构造函数1 拷贝构造
cout << endl;
cout << "########### 测试 emplace_back ###########" <<endl<< endl;
test.emplace_back(100, 200, "t3"); // 构造函数1
cout << endl;
test.emplace_back("t4"); // 构造函数2
cout << endl;
test.emplace_back(); //默认构造函数
cout << endl;
return 0;
}