【问题标题】:Are raw pointers automatically converted to smart pointers when emplaced and pushed to a vector of smart pointers?当放置并推送到智能指针向量时,原始指针是否会自动转换为智能指针?
【发布时间】:2019-09-06 22:12:01
【问题描述】:

我偶然发现了这样的代码:

std::vector<std::unique_ptr<Fruit>> fruits;
fruits.emplace_back(new Fruit);

(from here)

所以在代码中我们有一个原始指针(new 产生一个原始指针,对吗?)推入一个唯一指针向量。并且代码有效!但为什么?

因为这不会编译:

std::unique_ptr<Fruit> f = new Fruit();

为了方便起见,是不是有点神秘?

此外,这种方法而不是明确的fruits.emplace_back(std::make_unique&lt;Fruit&gt;()) 可能存在哪些缺陷?我读过make_unique 是创建唯一指针的首选方法。

【问题讨论】:

  • 请注意,对emplace_back 的调用有一个错误:如果emplace_back 抛出异常(内存不足),则会泄漏new Fruit
  • @Justin 你是指一般情况下,还是在这种情况下?
  • 这个案例。一般来说,如果你在emplace_back的调用中分配资源,期望资源归std::vector中创建的元素所有,如果分配失败,你会泄漏资源。
  • std::unique_ptr&lt;Fruit&gt; f(new Fruit()); 确实可以编译,并且等效于 emplace_back 所做的
  • @Justin 啊,我想我明白了,所以向量将无法释放分配的Fruit

标签: c++ pointers vector


【解决方案1】:

代码有效!但为什么?

vector::emplace_back 接受参数列表,然后将它们转发给它创建的元素的构造函数。

unique_ptr&lt;Fruit&gt;::unique_ptr(Fruit*) 是一个构造函数,它拥有传递的裸指针的所有权。

此外,这种方法可能存在哪些缺陷,而不是 [make_unique]

最大的陷阱是emplace_back 可能会抛出异常,在这种情况下没有成功创建unique_ptr。在这种情况下,传递给emplace_back() 的分配对象将被泄露。因此,最好传递unique_ptr 而不是裸指针,这样原始指针始终归某人所有。

关于使用new 而不是一般std::make_unique() 的次要问题:它使程序“不平衡”,从而阻止您使用古老的规则推理程序的正确性thumb "delete 的指针数量与您 new 的数量完全相同。"在这种情况下,您有一个正确的程序,其newdelete 多。这是否是一个问题是个人意见的问题。

【讨论】:

  • 谢谢。你知道make_unique 是否仍应被首选?
  • 这种new 的使用是正确的,除了vector.emplace_back 由于内存不足而抛出的极端情况。在这种情况下,new Fruit 泄漏。
  • @Justin 哦,对了。这是非常重要的。添加到答案中。
  • "在这种情况下,你有一个正确的程序,它的 newdelete" - 但实际上你没有。 delete 只是隐藏在 std::make_pointer() 返回的 unique_ptr 中,但它仍然存在。
  • @RemyLebeau The delete is merely hidden inside the unique_ptr 这正是重点。它不在你的代码中。它隐藏在别人的代码中。
【解决方案2】:
std::unique_ptr<Fruit> f = new Fruit();

没用,但是

std::unique_ptr<Fruit> f{new Fruit()};

有效。第一个不起作用,因为从语法上讲,它使用copy initialization。复制初始化不适用于std::unique_ptr,因为接受指针作为参数的构造函数是explicit

fruits.emplace_back(new Fruit);

因为上面使用的构造函数的存在而起作用。

【讨论】:

  • 谢谢。你知道我 make_unique 是否仍然应该比这个短版本更受欢迎?
  • @NurbolAlpysbayev,我个人更喜欢使用make_unique 而不是new Fruit。它消除了您自己代码中的new/delete 不平衡。由于我没有想到的原因,其他人可能更喜欢使用new Fruit
  • 谢谢!我已经决定选择make_unique,你加强了我的决定。
  • 赋值不起作用,因为接受指针的构造函数被标记为显式,而不是因为没有复制构造函数。
猜你喜欢
  • 2019-09-21
  • 1970-01-01
  • 2016-08-01
  • 1970-01-01
  • 2019-01-27
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 2016-10-09
相关资源
最近更新 更多