我创建了一个名为“ Resource”的类,并手工制作了构造函数,包括复制构造函数和move构造函数以及复制赋值和移动赋值运算符。
如我所料,插入右值时,仅调用move构造函数。当我插入一个左值时,进行了两个复制构造函数调用。
但是当我使用std :: move将左值转换为右值并使用push_back时,我感到很惊讶,我观察到一个移动构造函数的调用,随后是两次复制构造函数的调用。
经过一番思考,我猜想该复制是由向量在内部完成的。因此,我通过设置任何插入之前的容量来测试我的理论,并且观察到我发现std :: move和push_back没有复制。
class Resource
{
public:
Resource(std::string s) : str(std::move(s)) {}
~Resource() = default;
Resource(const Resource &r) {
std::cout << "Copy constructor" << std::endl;
str = r.str;
}
Resource& operator=(const Resource &r) {
std::cout << "Copy assignment" << std::endl;
if (this != &r)
{
str = r.str;
}
return *this;
}
Resource(Resource &&r) {
std::cout << "Move constructor" << std::endl;
str = std::move(r.str);
r.str.clear();
}
Resource& operator=(Resource &&r) {
std::cout << "Move assignment" << std::endl;
str = std::move(r.str);
r.str.clear();
return *this;
}
private:
std::string str;
};
int main()
{
std::vector<Resource> vec;
//vec.reserve(3);
vec.push_back(Resource("hello"));
Resource r("world");
vec.push_back(r);
vec.push_back(std::move(r));
return 0;
}
在main的第二行注释掉后得到:
移动构造函数
复制构造函数
复制构造函数
移动构造函数
复制构造函数
复制构造函数
当该行取消注释时,即我调用vec.reserve(3),我得到:
移动构造函数
复制构造函数
移动构造函数
这表明即使您定义了move构造函数,如果您没有保留足够的空间,也会继续进行复制。
有什么办法可以避免这种情况?
更新:我更正了=运算符以返回引用。我不知道您必须向编译器提供noexcept提示,以防止这种情况的发生。