使用 unique_ptr 的方法安全吗?

use*_*566 1 c++ unique-ptr

我有一些管理 unique_ptrs 队列的代码。在其主循环中,它从队列中弹出一个条目,对其执行某些操作,然后允许该元素超出范围并被删除。到目前为止,没有问题。

我想添加一个功能,我们可以将其移动到其他地方,而不是必须删除该元素。问题是只有元素本身知道是否执行此操作或它需要去哪里。

主循环类似于:

   std::deque< std::unique_ptr<Object> > queue;

   while( !queue.empty() ) {
      auto element = std::move( queue.front() );
      queue.pop_front();

      element->do_something();

      element->recycle( std::move(element) );  // ?
   }
Run Code Online (Sandbox Code Playgroud)

如果回收不是对象的方法,这将不是问题,但因为它是对象的方法,我不确定它应该是什么样子。通过上面的代码,我会得到类似的东西:

class Object {
public:

   virtual void do_something();
   
   virtual void recycle( std::unique_ptr<Object> unique_this ) {
     // move unique_this somewhere, or don't and allow it to be deleted
   }
};
Run Code Online (Sandbox Code Playgroud)

这安全吗?如果recycle不移动unique_this,它将在它自己的方法之一中删除它(不过在方法的末尾)。那是问题吗?

我想到避免删除这个的一种可能性是让recycle通过左值引用获取unique_ptr,我意识到这有点奇怪。这个想法是,如果它愿意,它会将其移动到某个地方,但如果不这样做,则直到回收返回后该对象才会被删除。不过,它不一定避免在其方法之一中可能删除对象的问题,因为我们必须确保无论我们将其移动到何处都不会立即删除它。

如果这样做不安全,后备计划是让 Object 返回一个回收器(即,一个不是执行回收的 Object 方法的可调用对象)。我认为这应该是可能的,但是考虑到不同的对象想要使用不同的回收器,管理回收器的类型和生命周期会有点混乱。

在我看来,第一个想法(按值传递 unqiue_ptr)是最好的,除非它违反任何规则。这样安全吗?有一个更好的方法吗?

Jar*_*d42 5

element->recycle(std::move(element));在 C++17 之前是有问题的: element->可能在移动构造函数之后求值,因此是nullptr。太不安全了。

那么更安全的做法是更改为:

virtual void recycle( std::unique_ptr<Object>&& unique_this )
Run Code Online (Sandbox Code Playgroud)

请记住,“移动”的不是std::move“移动”,而是移动结构。

选择

auto ptr = element.get(); // element might become nullptr just below,
                          // so kept "old" non-nullptr value
ptr->recycle(std::move(element));
Run Code Online (Sandbox Code Playgroud)

是可能的,但容易出错(需要注释,或者可能会在错误的代码中严重重构)

自 C++17 起,求值顺序 (13)指定element->在求值参数之前求值;所以它是安全的。

  • @user1806566如果我正确读取它,通过右值引用获取它并移动到函数内部的实例应该是安全的。所以 `void recycle( std::unique_ptr&lt;Object&gt;&amp;&amp; unique_this ) { if(die) { std::unique_ptr&lt;Object&gt; tmp(std::move(unique_this)); } else { /*移动到其他地方*/ } }` - 之前我从来不知道评估顺序规则的这种特殊含义。:) (2认同)
  • @user1806566:显示了 C++14 有效的方式,你需要纪律,Ted 的方式更安全。 (2认同)