【问题标题】:Move semantics with non-pointer data members使用非指针数据成员移动语义
【发布时间】:2016-09-18 22:10:12
【问题描述】:

可能已经有人问过并回答过了,但我不知道要搜索什么。

如果数据成员定义了移动赋值运算符,移动语义是否可以用于非指针数据成员?

假设我有一个类 M 定义 M::operator=(M&&) 像这样:

template <class T>
class M
{
public: 
    M()
    {
        mem_M = new T;
    }

    M& operator=(M&& src)
    {
        if (this != &src)
        {
            mem_M = src.mem_M;
            src.mem_M = nullptr;
        }
        return *this;
    }

private:    
    T* mem_M;
};

现在显然我可以有一个像这样的C&lt;T&gt; 类,带有一个不使用T 的移动赋值运算符的移动构造函数:

template <class T>
class C
{
public:
    C ()
    {
        mem_C = new T;
    }
    C (C&& rhs)
    {
        mem_C = rhs.mem_C;
        rhs.mem_C = nullptr;
    }

private:
    T* mem_C;
};

但是,如果我希望C&lt;T&gt;::mem_C 不是指针而是普通成员怎么办,我将如何处理移动函数中的C&lt;T&gt;::mem_C?我当然可以调用移动赋值运算符T::operator=(T&amp;&amp;) 将归档的mem_C 从一个实例移动到另一个实例,但是如何正确重置传递给C&lt;T&gt;::C(C&amp;&amp;)C 实例?

这至少在我看来是错误的:

template <class T>
class C
{
public:
    C ()
    {
        mem_C = T();
    }
    C (C<T>&& rhs)
    {
        mem_C = std::move(rhs.mem_C);
        rhs.mem_C = T();          // ?? like this?
    }

private:
    T mem_C;
};

那么,在移动函数中重置非指针数据成员的标准兼容方法是什么?

【问题讨论】:

  • 指针是“普通成员”的子集。您似乎在问移动类类型和非类类型之间的区别
  • mem_C = T(); 应该被移除,对象已经被构造,所以这只是浪费时间和资源。
  • 在这种情况下,您可以并且应该使用默认的移动赋值运算符(请参阅Rule of zero
  • @M.M 但如果mem_C 是一百万个元素的向量?释放该空间是否不值得花时间重新初始化mem_C
  • 嗯?例如,如果Tvector&lt;bla&gt;,那么当构造函数运行时它是一个空向量;将其设置为空向量不会释放任何东西,只会浪费时间。

标签: c++ pointers move-semantics


【解决方案1】:

所包含类型的移动赋值/构造函数必须使对象处于“可接受”状态,无论这对该类型意味着什么。被移动的类型之外的任何东西都不应负责维护对象的状态。

另外,您要确保在父移动构造函数中调用包含类型的移动构造函数,而不是包含类型的移动赋值 em> 就像你在你的例子中一样:

// move constructor calls move constructor of contained elements
C (C<T>&& rhs) : mem_c(std::move(rhs.mem_c))
{
    // anything in here is using already-constructed data members
}

// move assignment calls move assignment of contained elements
C & operator=(C<T>&& rhs) {
    mem_c = std::move(rhs.mem_c);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-05
    相关资源
    最近更新 更多