12.8复制和移动类对象
如果类X的定义未明确声明移动构造函数,则仅当且仅当将隐式声明为默认构造函数。
— X没有用户声明的副本构造函数,
— X没有用户声明的副本分配运算符,
— X没有用户声明的移动分配运算符,以及
— X没有用户声明的析构函数。[注意:如果未隐式声明或未明确提供move构造函数,则原本会调用move构造函数的表达式可以改为调用copy构造函数。—尾注]
我认为注释部分明确提到默认移动构造函数的后备类型将是复制构造函数。为了理解这个概念,我编写了一个小程序来理解这个概念。
#include<iostream>
struct handleclass {
public:
handleclass():length{0}, p{nullptr} {}
handleclass(size_t l):length{l},p{new int[length]} { }
~handleclass() { delete[] p; }
size_t length;
int* p;
};
handleclass function(void) {
handleclass x(10);
return x;
}
int main() {
handleclass y;
std::cout<<y.length<<std::endl;
y = function();
std::cout<<y.length<<std::endl;
handleclass a;
handleclass b(10);
a = std::move(b);
return 0;
}
显然,由于两个对象对资源的浅表复制,该程序是不正确的,并且具有未定义的行为(终止)。但是我的重点是了解在程序中生成和使用的默认move构造函数。我希望这个例子有意义。
在以上程序中,在两种情况下均应调用move构造函数时,在我看来编译器正在使用默认的拷贝构造函数。
基于标准中提到的上述规则,我认为我们应该遇到编译器错误,因为现在程序明确尝试调用move构造函数,并且用户没有实现,编译器也未生成default(隐式),因为上述规则不满足?
但是,此代码在没有任何警告/错误的情况下被编译并成功运行。有人可以解释一下默认(隐式)移动构造函数的概念吗?还是我错过了什么?
您会忘记复制省略,这意味着它y = function();
实际上可能不会调用任何复制或移动构造函数。只是构造函数x
和赋值运算符。
如该线程所述,某些编译器允许您禁用复制省略。
我不确定“在两种情况下都应调用move构造函数的情况”的含义。实际上,应该调用move构造函数的情况为零(您的对象没有move构造函数),而可以调用拷贝构造函数的情况(该return
语句)却被忽略了。
您有两种情况的赋值运算符:y = function();
和a = std::move(b);
。同样,由于您的班级没有移动分配运算符,因此它们将使用复制分配运算符。
如果您将代码cout
从复制构造函数中添加到对象中并移动构造函数,则可能会帮助您进行测试。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句