1 c++ destructor copy-constructor move-constructor
我创建了一个向量并使用push_back将几个节点对象放入其中。但是,我无法预测何时将使用移动构造函数或复制构造函数。
当push_back使用复制构造函数或移动构造函数时有什么模式吗?c++参考说它有时会复制,有时会移动,但从未详细说明它们何时做什么。
#include <iostream>
#include <vector>
#include <unordered_set>
#include <set>
#include <unordered_map>
#include <map>
#include <queue>
using namespace std;
struct Node {
int val;
Node(int val) : val(val) {
cout<<"created object" << val<<endl;
}
Node(const Node& m) : val(m.val) {
cout<<"copy constructor is called on value " << m.val << endl;
}
~Node() {
cout<<"destroyed val" << val<<endl;
}
Node(Node&& other) noexcept
: val(other.val) {
cout<<"moved val " << other.val << endl;
}
};
void f(vector<Node>& a) {
cout<<"______________________"<<endl;
Node tmp(12);
cout<<"12 established"<<endl;
a.push_back(tmp);
cout<<"a pushed back 12"<<endl;
a.push_back(Node(14));
cout<<"a pushed back tmp obj 14"<<endl;
tmp.val+=5;
cout<<"increased tmp.val"<<endl;
cout<<tmp.val<<endl;
cout<<a[1].val<<endl;
cout<<"two prints"<<endl;
cout<<"_______________"<<endl;
cout<<"end of f"<<endl;
// return a;
}
int main() {
vector<Node> a = {Node(125)}; //copied since initialized temp var.
a.reserve(4000);
cout<<"start of f"<<endl;
f(a);
cout<<"program ended"<<endl;
//noteiced: Copy constructor called upon local variable (12) that the vector knows will not stay with it --- and belongs to local scope.
//copy constructor not called upon temporary variable that soon belonged to vector (14).
//same thing with std::queue, std::stack, and many others.
//but it this a pattern or a coincidence?
}
Run Code Online (Sandbox Code Playgroud)
输出:
copy constructor is called on value 125
destroyed val125
moved val 125
destroyed val125
start of f
______________________
created object12
12 established
copy constructor is called on value 12
a pushed back 12
created object14
moved val 14
destroyed val14
a pushed back tmp obj 14
increased tmp.val
17
12
two prints
_______________
end of f
destroyed val17
program ended
destroyed val125
destroyed val12
destroyed val14```
Run Code Online (Sandbox Code Playgroud)
规则非常简单。
std::vector::push_back有两个重载。
第一个重载采用一个const T &参数。调用该重载使用对象的复制构造函数。
第二个重载采用一个T &&参数。调用该重载使用对象的移动构造函数。
请注意,两个重载最终可能会重新分配向量,这将触发一大堆移动,这不是重点。我还没有列出所有代码的诊断输出,但也有可能您正在记录由于重新分配而导致的移动,这进一步使问题变得混乱(尽管我看到您曾经reserve()摆脱过这一点,但它reserve()是在非-空向量,因此它唯一存在的值被移动,你可能也会对此感到困惑)。
所有这一切都假设T实现了移动语义。如果没有,那就都是复印件。
因此,您要做的只是确定给定的特定调用是否push_back()传递左值或右值。
a.push_back(tmp);
Run Code Online (Sandbox Code Playgroud)
tmp显然是一个左值。这最终将调用复制构造函数。
a.push_back(Node(14));
Run Code Online (Sandbox Code Playgroud)
该参数是一个右值。这最终将调用移动构造函数。
您可以使用相同的原理计算出其余的调用。
| 归档时间: |
|
| 查看次数: |
137 次 |
| 最近记录: |