c – 如何正确定义移动构造函数?

搜索了互联网,发现了3种定义移动构造函数方法

>依赖编译器:

T(T&& other) = default;

>取消引用这个指针:

T(T&& other) {
  *this = std::move(other);
}

>明确地重新分配所有成员:

T(T&& other) {
  T.a = other.a;
  T.b = other.b;
  //...
}

一个是正确的方法? (还有第二个甚至是正确的?)

解决方法

正确的通用方式是移动构建每个成员,但是这样做是反向版本的反正:
T(T && rhs)
: a(std::move(rhs.a)),b(std::move(rhs.b))
{  }

作为一个粗略的规则,如果这是所有你需要的,你应该使用认定义,如果你正在做一些显式实现移动语义的事情,你应该写一个显式的移动构造函数,比如唯一所有权资源管理器:

URM(URM && rhs)
: resource(rhs.resource)
{
    rhs.resource = nullptr;
}

这是否适合的指标可能是您的类是否具有用户定义的析构函数.在该示例中,析构函数将释放受管资源,并且必须仅发生一次,因此必须修改move-from对象.

这是无关紧要的,但是由于你提到了赋值运算符,所以这里是流行的交换和分配/交换成语:

void swap(URM & rhs) noexcept      // assume members are noexcept-swappable!
{
    using std::swap;
    swap(resource,rhs.resource);
    // ...
}

URM & operator=(URM rhs) noexcept  // pass by value
{
    rhs.swap(*this);
    return *this;
}

这种方法的优点是,您只需要一个适用于临时和非临时人员的分配运算符的单一版本,在适当时使用移动构建,只要所有成员都精心设计,您也只需要一个单次交换功能.除此之外,如果交换函数没有被抛出(一个精心设计的类应该允许的话),那么你的赋值运算符就不会抛出,因为所有可能的异常都会在调用站点发生.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...