【问题标题】:Inserting std::unique_ptr into std::set将 std::unique_ptr 插入 std::set
【发布时间】:2020-07-17 17:43:16
【问题描述】:

std::unique_ptr 使用std::make_unique() 插入std::set 的最佳方法是什么? insert()emplace() 都可以,但哪个更好?

【问题讨论】:

  • 对于std::unique_ptr 这样的类型并不重要。由于您在插入之前创建了std::unique_ptr,因此insert()emplace() 都必须为std::set 构造一个新的std::unique_ptr 以将您的std::unique_ptr 保存并移动到其中。如果您的std::set 持有实际对象而不是指向对象的指针,那么emplace()'ing 一个新对象将比insert()'ing 一个临时对象“更好”,但对于移动语义,差异往往可以忽略不计。
  • 我要构造unique_ptr "inline" 的插入。
  • 您可以使用emplace() 进行“内联”构造,但这意味着如果您想避免构造和传入临时std::unique_ptr 来转移所有权,则必须改为传入获取所有权的原始指针。这意味着如果emplace() 抛出,您将面临内存泄漏的风险。如果使用std::make_unique()作为输入,则指针始终受到保护,使用insert()emplace()几乎没有区别,所以随便用一个。
  • 如果insert() 抛出(而我使用std::make_unique())?
  • 如果你使用std::make_unique()作为输入,那么指针始终受到保护,无论你使用insert()还是emplace(),都不存在泄露风险

标签: c++ stl insert unique-ptr stdset


【解决方案1】:

unique_ptr 的实现方式(仅移动,而不是复制)可以防止您担心这种情况。但创造其他人:

s.insert( std::make_unique<X>(1) ); // SAFE

auto p2 = std::make_unique<X>(2);
s.insert( std::move(p2) ); // also safe

auto p3 = std::make_unique<X>(3); 
//s.insert( p3 ); // unsafe, compiler complains

s.emplace( std::make_unique<X>(4) ); // SAFE
auto p5 = std::make_unique<X>(5);
s.emplace( std::move(p5) ); // also safe

auto p6 = std::make_unique<X>(6);
//s.emplace( p6 );  // unsafe on exception, compiler will complain if you uncomment

auto p7 = std::make_unique<X>(7);
s.emplace( std::move(p7) ); // also safe
s.emplace( std::move(p7) ); // insert same agains also "safe", but inserts "null"
s.emplace( std::move(p2) ); // insert "null" again, but nulls are highlanders here 

https://godbolt.org/z/3Gfoo7

不管你是我们插入还是放置它总是通过移动语义发生,即使你s.insert( std::make_unique&lt;X&gt;(1) ),这是一个移动。

在此示例中,3 和 6 从未进入集合,即使您像示例中的最后两行 p7 或 p2 一样将其移动两次,它们在插入/放置到集合中之后将是“null”。

【讨论】:

  • “高地人”是什么意思?
  • 就像任何其他值一样,一个集合中只能有一个空值 >
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-16
  • 2020-08-06
  • 2014-03-27
  • 2012-09-28
  • 2019-11-07
相关资源
最近更新 更多