【发布时间】:2020-11-03 17:38:23
【问题描述】:
我曾经假设一个类的移动构造函数优先于其复制构造函数,但在下面的代码中,似乎选择了复制构造函数,即使对象应该是可移动的。
你知道为什么下面的代码在foo()返回vector<B> B时选择复制构造函数吗?
#include <iostream>
#include <vector>
using namespace std;
class B {
public:
int var_;
B(int var) : var_(var)
{
cout << "I'm normal" << endl;
}
B(const B& other)
{
cout << "I'm copy constructor" << endl;
}
B(B&& other)
{
cout << "I'm move constructor" << endl;
}
};
vector<B> foo()
{
vector<B> b;
b.push_back(1);
b.push_back(2);
return b;
}
int main()
{
vector<B> b {foo()};
}
结果如下图。
$ g++ main.cpp
$ a.out
I'm normal
I'm move constructor
I'm normal
I'm move constructor
I'm copy constructor
奇怪的是,如果我删除foo() 中的一行,则会选择移动构造函数:
vector<B> foo()
{
vector<B> b;
b.push_back(1);
return b;
}
现在结果如下:
$ g++ main.cpp
$ a.out
I'm normal
I'm move constructor
【问题讨论】:
-
当向量被移动时,它的元素完全不受影响。
-
第二个
push_back导致向量被调整大小和重新分配;然后将现有数据从旧数据复制到新数据。在您的main中添加b.reserve(3);,您将看不到副本。 -
向量在插入时复制其内容以展开(与返回无关)。这样做是因为您的移动构造函数可能会抛出。所以它做动作是不安全的。声明
B(B&& other) noexcept -
如果你在
return b;之前打印了一些东西,你会注意到在向量返回之前所有的移动和复制都已经完成了。 -
谢谢大家,我学到了很多!
标签: c++ vector g++ move-semantics