其他分享
首页 > 其他分享> > c – 只是添加析构函数,什么也不做会导致编译错误(围绕std :: move),为什么?

c – 只是添加析构函数,什么也不做会导致编译错误(围绕std :: move),为什么?

作者:互联网

当我学习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;
}

实时代码:https://ideone.com/UTR9ob

该错误是’B&’类型的非const引用的无效初始化来自’std :: remove_reference< B&> :: type {aka B}’类型的右值.

题:

>(1)C语法的哪些规则强制执行?换句话说,错误是什么意思?
>(2)如果我想添加几乎不做任何事情的析构函数(例如只打印调试日志)到B,我真的必须遵循五法则吗?如果没有,如何编译?由于这个原因,遵循五条规则在我看来太繁琐和肮脏.

我认为零规则只是一种很好的做法.

但是,从这个例子来看,在我看来这是一个很难的规则,如果违反,我将得到编译错误.

解决方法:

隐式声明的移动构造函数仅在类没有用户声明的析构函数时才存在.因此,2的答案是肯定的.

答案是1.这是一个很难的规则,可以在标准的第12.8段中找到:

If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared
as defaulted if and only if

  • X does not have a user-declared copy constructor,
  • X does not have a user-declared copy assignment operator,
  • X does not have a user-declared move assignment operator,
  • X does not have a user-declared destructor, and
  • the move constructor would not be implicitly defined as deleted.

[ Note: When the move constructor is not implicitly declared or explicitly supplied, expressions that
otherwise would have invoked the move constructor may instead invoke a copy constructor. — end note ]

让它运行的最好方法是使用类似智能指针的东西,即基类或成员定义所有五个特殊成员(以及其他很少的成员),这样你就不必这样做了.在这种情况下,等效于std :: unique_pointer的整数句柄应该可以正常工作.但是,请记住,数据库(如文件)在关闭时可能会出错,因此标准的非抛出析构函数语义不会涵盖所有情况.

标签:rule-of-zero,c,c11,move-semantics
来源: https://codeday.me/bug/20190828/1754867.html