即使我实现了副本分配运算符,类还是可以移动构造和分配的

时间:2019-06-13 00:33:08

标签: c++

The C++ Programming Language 4th edition中,作者说

  

•如果程序员声明了某个类的复制操作,移动操作或析构函数,则不会为该类生成任何复制操作,移动操作或析构函数。

     

•如果程序员为类声明任何构造函数,则不会为该类生成默认构造函数。

因此,我试图在实际中看到这一点,所以我实现了本书中的一个示例,一个具有std::vector成员的简单类,一个默认构造函数的实现和一个复制赋值运算符。

#include <iostream>
#include <vector>
#include <type_traits>

class tic {
public:
    tic() : p(9) {}

    tic &operator=(const tic& t) {
        for(int i = 0; i < t.p.size(); i++)
            p.at(i) = t.p.at(i);
        return *this;
    }

private:
    std::vector<int> p;
};

int main() {
    std::cout << std::boolalpha;
    std::cout << std::is_move_constructible<tic>::value <<  
          ' ' << std::is_move_assignable<tic>::value;
    return 0;
}

我不明白为什么输出 true true?我尝试实现默认构造函数以外的其他构造函数,但无法使用指定的生成的默认构造函数,但是在复制分配的情况下,我已经实现了它,并且该类仍可移动分配并且可以构建。

1 个答案:

答案 0 :(得分:5)

std::is_move_assignable仅检查是否可以从自身的右值分配目标类。 const左值引用可以绑定到右值,因此只要declval<tic&>() = declval<tic&&>()进行编译,std::is_move_assignable就会返回true。

为了更加明确,可以将移动分配运算符设置为deleted。这样,它就可以参与过载解析,并且可分配移动检查将失败。