【问题标题】:Is it safe to use emplace_back with a container of unique_ptrs?将 emplace_back 与 unique_ptrs 容器一起使用是否安全?
【发布时间】:2012-10-21 19:02:17
【问题描述】:

考虑以下几点:

std::vector<std::unique_ptr<int>> ptrsToInts;
ptrsToInts.emplace_back(new int);

如果向量中发生重新分配并且失败(抛出std::bad_alloc),我是“安全”还是会泄漏int

C++11 23.3.6.5 [vector.modifiers]/1 说:

如果除了T 的复制构造函数、移动构造函数、赋值运算符或移动赋值运算符或任何InputIterator 操作引发异常,则没有任何影响。

这似乎表明这是一个潜在的问题。也就是说,如果没有“影响”,则不会构造任何 unique_ptr,因此不会出现指向 delete 的析构函数行为。 (这可能表明emplace_back 应该被禁止用于unique_ptrs 的容器)

【问题讨论】:

  • 好点。这启发了我完全放弃使用new 转而使用std::make_unique,这样我就可以从一开始就知道每个分配都以智能指针结束。
  • 我在评论中注意到了这个陷阱:stackoverflow.com/questions/3283778/…

标签: c++ emplace exception-safety


【解决方案1】:

如果需要重新分配但它失败了,那么是的,你的对象永远不会进入容器,因此会丢失。

但是,需要注意的是,这纯属用户错误。对于unique_ptr 的容器,emplace_back 不应该被“禁止”,因为有非常安全的方法可以做到这一点(例如reserve预先分配空间,所以你知道它会一直存在)。此外,您可以传入整个 unique_ptrs,因为它完全可以使用移动构造函数。

所以说真的,在可能引发异常的点之前没有正确地将非 RAII 对象(int*)包装在 RAII 对象中是你的错。

【讨论】:

  • 啊——但该对象从未进入。Emplacement 在向量内存块本身内部就地构造对象。传入的是指针,而不是unique_ptr。当然,指针被销毁了,但是我有保证unique_ptr的析构函数运行并删除指针吗?
  • 实际上,emplace 是异常的无操作,而是说明int 没有正确获取deleted,因为它的分配完全发生在emplace 之外,而(释放)智能指针的构造发生在内部。
  • Erm,因为什么时候需要在这里分配“故障”?至于有“完全安全”的方法可以做到这一点,当然,有“安全”的方法可以做到这一点。但是,如果你强制使用移动构造函数,你不妨改用push_back,因为它在所有情况下都会强制执行正确的行为。
  • @BillyONEal:至于“错误”,您建议这应该被“禁止”(无论是什么意思)。这意味着您认为语言/API 是错误的,应该避免使用。因此,如果您遇到这个问题,那是语言/API 的错,而不是程序员的错。如果只是用户错误,没有理由禁止它,对吧?
  • @Nicol: 嗯...不是我所说的禁止。让我们说“非常气馁”。
猜你喜欢
  • 2012-07-26
  • 2021-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-13
  • 2021-11-07
  • 2011-12-04
相关资源
最近更新 更多