"继承"移动操作而无需访问基类成员变量

时间:2015-09-09 15:56:24

标签: c++ inheritance move-semantics

作为rvalue引用的新手并移动语义,我试图从std::vector派生一个简单的模板类(我保证我会对缺少虚拟析构函数小心)。为了继承"移动构造函数,我只是调用基类对应的std::move

template <typename T>
class Vec: public std::vector<T> {
  public:
    ...
    //move ctors
    Vec(Vec&& v): std::vector<T>(v) { //move extra members with std::move }
    explicit Vec(std::vector<T>&& v): std::vector<T>(v) { //same as above }
    ...
};

基于我对C ++的理解,它似乎值得信赖。但是,我对移动赋值运算符的方法信心不足,

    //assignment
    Vec& operator=(const Vec& v) {
        std::vector<T>::operator=(v);
        if (&v != this)
          //copy extra members
        return *this;
    }
    //move assignment
    Vec& operator=(Vec&& v) {
        std::vector<T>::operator=(v);
        //move extra members with std::move
        return *this;
    }

这是实现我想要的万无一失的方式吗?在良好实践方面是否有更好的选择?

1 个答案:

答案 0 :(得分:4)

  

似乎值得信赖......

似乎值得信赖。但事实并非如此。你看,这个:

Vec(Vec&& v)

是一个移动构造函数。所以它会被rvalue调用。但是一旦我们进入这里,v就是一个左右!经验法则:如果它有名字,那就是左值。所以这一部分:

: std::vector<T>(v)

不会调用std::vector move 构造函数。它调用 copy 构造函数。您需要将v明确地转换为右值才能做正确的事情:

Vec(Vec&& v) : std::vector<T>(std::move(v)) { }
explicit Vec(std::vector<T>&& v): std::vector<T>(std::move(v)) { }

或者,更好的是:

Vec(Vec&& ) = default;

同样,编写赋值运算符的简单方法只是default - 它们:

Vec& operator=(Vec const& ) = default;
Vec& operator=(Vec&& ) = default;

但如果你真的有特殊的逻辑,那么请确保你也记得在那里施放rvalue:

Vec& operator=(Vec&& v) {
    std::vector<T>::operator=(std::move(v));
    // stuff
    return *this;
}

甚至更好,将您的特殊逻辑转移到一个独立的单元,以便default - 仍然是正确的。