如果对象的构造函数是noexcept,则可以放置new(expression)吗?

时间:2014-06-17 14:25:38

标签: c++ exception c++11 placement-new noexcept

template <class T>
struct Obj {
  // Plain Old Data for T
  using InternalPod = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;

  InternalPod value_pod_;

  template<class... Args>
  Obj(Args&&... args) { // my constructor
    // placement new: construct the value in the statically allocated space
    new (&value_pod_) T(std::forward<Args>(args)...); // <- can this whole expression throw if the constructor of T doesn’t throw?
  }
}

正常 new如果分配失败或构造失败可以抛出(如果有其他情况则纠正我),但由于贴片new不分配任何空间,可以如果T的构造函数没有抛出,那么抛出新表达式?

即。以下noexcept规范是否正确且安全?

Obj(Args&&... args) noexcept(noexcept(T(std::forward<Args>(args)...))) {
  new (&value_pod_) T(std::forward<Args>(args)...);
}

1 个答案:

答案 0 :(得分:11)

根据18.6 [support.dynamic]第1段,来自new的展示位置<new>被声明为noexcept

  

... void* operator new (std::size_t size, void* ptr) noexcept; ...

使用new表达式时,系统完成两件事:

  1. 调用适当版本的operator new()来获取内存。如果内存分配失败,它应该为std::bad_alloc抛出operator new()而没有noexcept限定条件,否则返回nullptr
  2. 如果返回非nullptr,则表达式将调用new表达式中类型的构造函数。如果此构造因异常而失败,则调用匹配被调用operator delete()的{​​{1}},其结果来自operator new()
  3. 由于内存分配无法失败,因此获取异常的唯一选择是来自类型的构造函数。