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)...);
}
答案 0 :(得分:11)
根据18.6 [support.dynamic]第1段,来自new
的展示位置<new>
被声明为noexcept
:
...
void* operator new (std::size_t size, void* ptr) noexcept;
...
使用new
表达式时,系统完成两件事:
operator new()
来获取内存。如果内存分配失败,它应该为std::bad_alloc
抛出operator new()
而没有noexcept
限定条件,否则返回nullptr
。nullptr
,则表达式将调用new
表达式中类型的构造函数。如果此构造因异常而失败,则调用匹配被调用operator delete()
的{{1}},其结果来自operator new()
。由于内存分配无法失败,因此获取异常的唯一选择是来自类型的构造函数。