C++ STL库中双向队列deque的emplace_back与push_back区别
一、按传参类型分类
1. 传入左值
当传参类型为左值时,没有区别。都经历了:
- 调用 构造 函数,构造出右值 T
- 调用 拷贝构造 函数,copy 数据到 vector 的数据空间 的对象 A
- 在参数声明周期结束后,调用 T 的 析构 函数
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node() {
cout << "constructor" << endl;
}
Node(int _val) {
cout << "constructor 1: val = " << _val << endl;
val = _val;
left = NULL;
right = NULL;
}
Node(int _val, Node* _left, Node* _right) {
cout << "constructor 2: val = " << _val << endl;
val = _val;
left = _left;
right = _right;
}
Node(const Node& other) {
cout << "[copy] val = " << other.val << endl;
val = other.val;
left = other.left;
right = other.right;
}
~Node() {
cout << "deconstructor: val = " << val << endl;
}
};
int main() {
deque<Node> A;
cout << "======= 左值对比 =======" << endl;
cout << "push_back 左值" << endl;
Node t1 = Node(11);
A.push_back(t1);
cout << endl;
cout << "emplace_back 左值" << endl;
Node t2 = Node(22);
A.emplace_back(t2);
cout << endl;
return 0;
}
2. 传入右值
a. 当传参类型为右值且非in place构造时,两者没有区别。都经历了:
- 调用 构造 函数,构造出右值 T
- 调用 拷贝构造 函数,copy 数据到 vector 的数据空间 的对象 A
- 在参数声明周期结束后,调用 T 的 析构 函数
此时与左值传递唯一不同之处在于,右值的构造函数是在传递时临时调用的,语句执行完毕则即可执行析构函数,左值传递则会等到超出该变量作用域时执行析构函数。
b. 只有emplace能进行in place构造,此时可以省去一次拷贝构造函数的调用
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node() {
cout << "constructor" << endl;
}
Node(int _val) {
cout << "constructor 1: val = " << _val << endl;
val = _val;
left = NULL;
right = NULL;
}
Node(int _val, Node* _left, Node* _right) {
cout << "constructor 2: val = " << _val << endl;
val = _val;
left = _left;
right = _right;
}
Node(const Node& other) {
cout << "[copy] val = " << other.val << endl;
val = other.val;
left = other.left;
right = other.right;
}
~Node() {
cout << "deconstructor: val = " << val << endl;
}
};
int main() {
deque<Node> A;
cout << "======= 右值对比 =======\n" << endl;
cout << "emplace_back 右值" << endl;
A.emplace_back(Node(3));
cout << endl;
cout << "emplace_back in-place 构造" << endl;
A.emplace_back(4, nullptr, nullptr);
cout << endl;
cout << "push_back 右值" << endl;
A.push_back(Node(5));
cout << endl;
return 0;
}