9
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?
  }
}

如果分配失败或构造失败, Normal new可以抛出(如果有其他情况,请纠正我),但由于放置 new 不分配任何空间,如果构造函数T不抛出,新表达式可以抛出吗?

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

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

1 回答 1

15

根据 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。如果此构造因异常而失败,则使用 that 的结果调用operator delete()匹配的被调用者。operator new()operator new()

由于内存分配不会失败,因此获得异常的唯一选择是来自类型的构造函数。

于 2014-06-17T14:31:52.840 回答