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

"Inherit" move operations without access to base-class member variables

本文关键字:访问 基类 成员 变量 Inherit 移动 操作      更新时间:2023-10-16

作为右值引用和移动语义的新手,我试图从std::vector派生一个简单的模板类(我保证我会小心缺少虚拟析构函数)。要"继承"move构造函数,我只需调用基类的对应类和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;
    }

这是一个万无一失的方法来实现我想要的吗?就良好实践而言,是否有更好的替代方案?

这似乎是值得信赖的…

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

Vec(Vec&& v)

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

: std::vector<T>(v)

不调用std::vectormove构造函数。它调用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;

但是如果你真的有特殊的逻辑,确保你也记得在那里转换为右值:

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

或者更好的是,将您的特殊逻辑移动到一个独立的单元中,这样default -ing仍然是正确的。