当使用push_back()时,看如下代码,先构造变量a,再调用push_back()
代码如下:
#include <iostream>
#include<vector>
using namespace std;
class testDemo
{
public:
testDemo(int num):num(num){
std::cout <<"调用构造函数"<< endl;
}
testDemo(const testDemo& other):num(other.num){
std::cout <<"调用拷贝构造函数"<< endl;
}
private:
int num;
};
int main()
{
vector<testDemo> values{};
testDemo a(1);
cout << "开始push_back1 \n";
values.push_back(a);
cout << "结束push_back1 \n";
return 0;
}
代码运行有如下输出:
调用构造函数
开始push_back1
调用拷贝构造函数
结束push_back1
Program ended with exit code: 0
从以上输出可以看到,将已构造好的元素 a 使用push_back()插入vector时,只调用了拷贝构造函数。
当使用emplace_back()时,看如下代码,先构造变量a,再调用emplace_back()
#include <iostream>
#include<vector>
using namespace std;
class testDemo
{
public:
testDemo(int num):num(num){
std::cout <<"调用构造函数"<< endl;
}
testDemo(const testDemo& other):num(other.num){
std::cout <<"调用拷贝构造函数"<< endl;
}
private:
int num;
};
int main()
{
vector<testDemo>values{};
testDemo a(1);
cout << "开始emplace_back1 \n";
values.emplace_back(a);
cout << "结束emplace_back1 \n";
return 0;
}
代码运行有如下输出:
调用构造函数
开始emplace_back1
调用拷贝构造函数
结束emplace_back1
Program ended with exit code: 0
从以上输出可以看到,将已构造好的元素 a 使用emplace_back()插入vector时,只调用了 拷贝构造函数。
从上面两组实验可知,插入一个已经构造好的数据时,push_back()和emplace_back()都是调用拷贝构造函数,效率应该差不多一致。
当使用push_back()时,看如下代码,将一个int类型的数字,作为push_back()的参数。
#include <iostream>
#include<vector>
using namespace std;
class testDemo
{
public:
testDemo(int num):num(num){
std::cout <<"调用构造函数"<< endl;
}
testDemo(const testDemo& other):num(other.num){
std::cout <<"调用拷贝构造函数"<< endl;
}
private:
int num;
};
int main()
{
vector<testDemo>values{};
cout << "开始push_back1 \n";
values.push_back(1);
cout << "结束push_back1 \n";
return 0;
}
代码运行有如下输出:
开始push_back1
调用构造函数
调用拷贝构造函数
结束push_back1
Program ended with exit code: 0
从以上输出可以看到,push_back的参数是数字 1 时,需要调用构造函数和拷贝构造函数。
当使用emplace_back()时,看如下代码,将一个int类型的数字,作为emplace_back()的参数。
代码如下:
#include <iostream>
#include<vector>
using namespace std;
class testDemo
{
public:
testDemo(int num):num(num){
std::cout <<"调用构造函数"<< endl;
}
testDemo(const testDemo& other):num(other.num){
std::cout <<"调用拷贝构造函数"<< endl;
}
private:
int num;
};
int main()
{
vector<testDemo>values{};
cout << "开始emplace_back1 \n";
values.emplace_back(1);
cout << "结束emplace_back1 \n";
return 0;
}
代码运行有如下输出:
开始emplace_back1
调用构造函数
结束emplace_back1
Program ended with exit code: 0
从以上输出可以看到,emplace_back()的参数是数字 1 时,只需要调用构造函数。而不像 push_back 要同时调用构造函数和拷贝构造函数。
所以这里就是大家通常认为 emplace_back 比 push_back的效率要高的地方。push_back 要先将参数构造成类型testDemo的,然后调用拷贝构造函数复制到vector的末尾,而 emplace_back可以根据参数直接在vector的末尾构造数据,省去了拷贝的过程。
简化版本的 push_back源码:
template <typename T>
void vector<T>::push_back(const T& value) {
//这里类型转换调用构造函数
if (size == capacity) {
expand_capacity();
}
data[size] = value; // 这里调用 构造函数
size++;
}
看上面的代码:
如果输入参数和类型不一致,就会发生类型转换,调用构造函数,生成临时变量。
调用拷贝构造函数将数据拷贝到vector。
template <typename T>
template <typename... Args>
void vector<T>::emplace_back(Args&&... args) { // 可变参参数
if (size == capacity) {
expand_capacity();
}
// 使用传入的参数在vector的内存空间中直接构造一个对象,
// 调用构造函数
new (&data[size]) T(std::forward<Args>(args)...);
size++;
}
看上面的代码:
? 2. 调用构造函数,在vector中原地构造数据。
总的来说,emplace_back()和push_back()都是用于向容器的尾部插入新元素的函数。它们的最大区别在于emplace_back()直接在容器内部构造新元素,而push_back()是将一个已存在的元素的副本拷贝到容器中。
使用emplace_back()可以避免额外的元素拷贝操作,因为它直接在容器内部构造了新元素。这对于一些体积较大或有复杂构造函数的元素来说尤为重要,可以提高效率并减少资源的消耗。另外,emplace_back()还接受构造新元素所需的参数,使得代码更加简洁明了。