jav*_*ver 3 c++ move-semantics c++11 rule-of-zero
在我学习的过程中std::move,我发现了一个奇怪的问题.
如果我只添加一个对完美程序无效的析构函数,我将收到编译错误.
#include <iostream>
using namespace std;
class M {
public:
int database = 0;
M &operator=(M &&other) {
this->database = other.database;
other.database = 0;
return *this;
}
M(M &&other) { *this = std::move(other); }
M(M &m) = default;
M() = default;
~M() { /* free db */ }
};
class B {
public:
M shouldMove;
//~B(){} //<--- ## Adding this line will cause compile error. ##
};
int main() {
B b;
B b2 = std::move(b); //## error at this line if the above line is added
return 0;
}
Run Code Online (Sandbox Code Playgroud)
实时代码:https://ideone.com/UTR9ob
错误是 invalid initialization of non-const reference of type 'B&' from an rvalue of type 'std::remove_reference<B&>::type {aka B}'.
B,我真的必须遵循五法则吗?如果没有,如何编译?由于这个原因,遵循五条规则在我看来太繁琐和肮脏.我认为零规则只是一种很好的做法.
但是,从这个例子来看,在我看来这是一个很难的规则,如果违反,我将得到编译错误.
隐式声明的移动构造函数仅在类没有用户声明的析构函数时才存在.因此,2的答案是肯定的.
答案是1.这是一个很难的规则,可以在标准的第12.8段中找到:
如果类X的定义没有显式地声明一个移动构造函数,那么当且仅当一个移动构造函数被隐式声明为默认值时
- X没有用户声明的复制构造函数,
- X没有用户声明的复制赋值运算符,
- X没有用户声明的移动赋值运算符,
- X没有用户声明的析构函数,和
- 移动构造函数不会被隐式定义为已删除.
[注意:当未隐式声明或显式提供移动构造函数时,否则将调用移动构造函数的表达式可能会调用复制构造函数. - 结束说明]
让它运行的最好方法是使用类似智能指针的东西,即基类或成员定义所有五个特殊成员(以及其他很少的成员),这样你就不必这样做了.在这种情况下,等效的整数句柄std::unique_pointer应该可以正常工作.但是,请记住,数据库(如文件)在关闭时可能会出错,因此标准的非抛出析构函数语义不会涵盖所有情况.
| 归档时间: |
|
| 查看次数: |
127 次 |
| 最近记录: |