之后仍需要使用源对象时调用父移动赋值运算符

Calling parent move assignment operator when source object still needs to be used after

TLDR - 如果是这样,请随意将其标记为重复;我会删除问题。然而,我四处寻找了一番,却一无所获。

考虑以下 类:

class Base
{
public:
    Base(std::string var1);

    Base& operator=(Base&& other) noexcept
    {
        if (this != &other)
            var1_ = std::move(other.var1_);
        return *this;
    }

protected:
    std::string var1_;
};

class Child final : public Base
{
public:
    Child(std::string var1, std::string var2);

    Child& operator=(Child&& other) noexcept
    {
        if (this != &other)
        {
            // Take note of HERE for explanation below
            Base::operator=(std::move(other));
            var2_ = std::move(other.var2_);
        }
    }

private:
    std::string var2_;
};

这里有两个类,Child 派生自BaseChild 的成员多于 Base。在 Child 的移动赋值运算符中,我们有一种情况,我们有额外的成员也需要分配给 other 的成员的值。但是,我们首先将 other 的内存移动到父移动赋值运算符,那么该数据不会无法使用吗?

我想我只是对 (1) 如果我上面的内容确实有任何问题感到困惑,(2) 如果是这样,为什么它会起作用,因为 other 应该在它之前移动被使用,并且 (3) 如果没有,完成我的任务的最佳方法是什么?

是否更好的方法是先初始化 Child 的成员,然后 然后 将其交给 Base 移动赋值运算符?有区别吗?

是的,这是安全的。

首先,请注意关于不使用移出对象的规则是设计和使用对象的默认准则。这不是语言本身的规则。这是 class 对象 通常 在它们被移出后保证的常见做法,包括未指定的标准库 class 类型(例如std::unique_ptr<T> 保证移出指针持有空指针)。

因此,既然您确切地知道 Base::operator=other 做了什么,并且只从 other.var1_ 移动,那么使用 other.var2_.[=26= 仍然是安全的]

此模式安全的另一个原因是,即使您实际上并不确切知道 Base::operator= 的作用,或者您想要编写 Child 代码以继续工作,即使细节Base 变化。 Child 对象包含两个子对象:Base 基础 class 子对象和 var2_ 成员子对象。这些对象天生就不知道对方的任何信息。 (他们可以通过指针、虚函数等手动设置彼此之间的交互,使事情复杂化,但这类事情应该在 Base 中记录或在 Child 中已知) [= =23=] 语句仅从基础 class 子对象移动,而不是从成员子对象移动,因此成员子对象不受影响,并且 Child::operator=(Child&&) 的定义对于 Base 的更改是安全的.