加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 提供正确的移动语义

发布时间:2020-12-16 10:30:44 所属栏目:百科 来源:网络整理
导读:我目前正试图弄清楚如何使用包含指向已分配内存的指针的对象正确地移动语义.我有一个大的数据结构,其中包含一个指向实际存储的内部原始指针(出于效率原因).现在我添加了一个移动构造函数并移动operator =().在这些方法中,我是std :: move()指向新结构的指针.
我目前正试图弄清楚如何使用包含指向已分配内存的指针的对象正确地移动语义.我有一个大的数据结构,其中包含一个指向实际存储的内部原始指针(出于效率原因).现在我添加了一个移动构造函数并移动operator =().在这些方法中,我是std :: move()指向新结构的指针.但是我不知道如何处理来自其他结构的指针.

这是我正在做的一个简单的例子:

class big_and_complicated {
   // lots of complicated code
};

class structure {
public:
   structure() :
      m_data( new big_and_complicated() )
   {}

   structure( structure && rhs ) :
      m_data( std::move( rhs.m_data ) )
   {
      // Maybe do something to rhs here?
   }

   ~structure()
   {
      delete m_data;
   }

private:
   big_and_complicated * m_data;
}

int main() {
  structure s1;
  structure s2( std::move( s1 ) );
  return 0;
}

根据我的理解,在std :: move(s1)到s2之后,唯一可以安全地在s1上做的就是调用它的构造函数.但是据我所知,这将导致删除析构函数中s1中包含的指针,使s2也无用.所以我猜我在std :: move()指针时必须做一些事情来渲染析构函数.据我所知,最安全的做法是在移动的对象中将其设置为0,因为这会在以后将删除变为无操作.到目前为止,这种推理是否正确?或者std :: move()实际上足够聪明,为我指出了指针,使其使用安全吗?到目前为止,我看到实际测试套件中没有崩溃,但我还没确定实际调用了move-constructor.

解决方法

“移动”指针与复制指针没有什么不同,也没有将move-from值设置为null(‘moving’在引号中,因为std :: move不会真正移动任何东西,它只是改变了参数的值类别).只需复制rhs’指针然后将其设置为nullptr:

struct structure
{
    structure()
      : m_data{new big_and_complicated{}}
    { }

    structure(structure&& rhs)
      : m_data{rhs.m_data}
    {
        rhs.m_data = nullptr;
    }

    structure& operator =(structure&& rhs)
    {
        if (this != &rhs)
        {
            delete m_data;
            m_data = rhs.m_data;
            rhs.m_data = nullptr;
        }
        return *this;
    }

    ~structure()
    {
        delete m_data;
    }

private:
    big_and_complicated* m_data;

    structure(structure const&) = delete;             // for exposition only
    structure& operator =(structure const&) = delete; // for exposition only
}

更好的是,使用std :: unique_ptr< big_and_complicated>而不是big_and_complicated *,你不需要自己定义任何一个:

#include <memory>

struct structure
{
    structure()
      : m_data{new big_and_complicated{}}
    { }

private:
    std::unique_ptr<big_and_complicated> m_data;
}

最后,除非你真的希望结构保持不可复制,否则你最好只在big_and_complicated中实现正确的移动语义,并让结构直接保存big_and_complicated对象.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读