繁体   English   中英

C ++移动赋值运算符:我是否想要将std :: swap与POD类型一起使用?

[英]C++ Move assignment operator: Do I want to be using std::swap with POD types?

从C ++ 11开始,当使用移动赋值运算符时,我应该std::swap所有数据,包括POD类型吗? 我想这对下面的例子没什么影响,但我想知道普遍接受的最佳做法是什么。

示例代码:

class a
{

     double* m_d;
     unsigned int n;

public:

     /// Another question: Should this be a const reference return?
     const a& operator=(a&& other)
     {
         std::swap(m_d, other.m_d); /// correct
         std::swap(n, other.n); /// correct ?
         /// or
         // n = other.n;
         // other.n = 0;
     }
}

您可能想要考虑以下形式的构造函数: - ie:在nm_d中始终存在“有意义”或定义的值存储。

a() : m_d(nullptr), n(0)
{
}

我认为这应该以这种方式重写。

class a
{
public:
     a& operator=(a&& other)
     {
         delete this->m_d; // avoid leaking
         this->m_d = other.m_d;
         other.m_d = nullptr;
         this->n = other.n;
         other.n = 0; // n may represents array size
         return *this;
     }
private:
    double* m_d;
    unsigned int n;
};

不,如果效率是任何问题,请不要交换POD。 与正常分配相比,没有任何好处,它只会导致不必要的副本。 还要考虑是否甚至需要将从POD移动到0的设置。

我甚至不会交换指针。 如果这是一个拥有关系,请使用unique_ptr并从中移动,否则将其视为POD(将其复制并在之后将其设置为nullptr或程序逻辑需要的任何内容)。

如果您不必将POD设置为零并且使用智能指针,则根本不需要实现移动运算符。

关于你的问题的第二部分:正如Mateusz所说,赋值运算符应该总是返回一个正常(非常量)引用。

我应该std ::交换我的所有数据

不一般。 移动语义可以使事情变得更快,并且交换直接存储在对象中的数据通常比复制它更慢,并且可能为某些移动的数据成员分配一些值。

针对您的具体情况......

class a
{
     double* m_d;
     unsigned int n; 

......只考虑数据成员才知道什么才有意义是不够的。 例如,如果您对非POD成员使用假定的交换组合,则另外...

     std::swap(m_d, other.m_d);
     n = other.n;
     other.n = 0;

...在移动构造函数或赋值运算符中,如果说析构函数在n0时跳过删除m_d ,或者在使用指向新分配的内存的指针覆盖m_d之前检查n == 0 ,则它仍可能使程序状态无效,旧记忆可能会泄露。 您必须决定类不变量: m_dn的有效关系,以确保您的移动构造函数和/或赋值运算符使状态对将来的操作有效。 (大多数情况下,移动对象的析构函数可能是唯一可以运行的东西,但它对于重用移动对象的程序是有效的 - 例如,为其分配一个新值并在循环的下一次迭代中处理它....)

另外,如果你的不变量在n == 0时允许非nullptr m_d ,那么交换m_d s很吸引人,因为它给移动对象持续控制移动对象可能具有的任何缓冲区:这可以节省时间分配稍后缓冲; 反平衡,亲,如果缓冲区不需要以后你保持分配超过必要的时间,如果它不够大,你将最终删除和新增一个​​更大的缓冲区,但至少你是懒惰的这往往有助于提高绩效(但如果你需要关心,可以提供资料)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM