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

通常 newは、割り当てが失敗した場合、または構築が失敗した場合にスローできます (他のケースがある場合は修正してください)。ただし、配置 new はスペースを割り当てないため、コンストラクターがTスローしない場合、new 式はスローできますか?

つまり、次のnoexcept仕様は正しく安全ですか?

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

1 に答える 1

15

newからの配置は、18.6 [support.dynamic] パラグラフ 1 に従って<new>宣言されています。noexcept

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

式を使用するnew場合、システムは次の 2 つのことを行います。

  1. の適切なバージョンを呼び出して、operator new()メモリを取得します。メモリの割り当てに失敗した場合は、修飾なしで をスローstd::bad_allocし、それ以外の場合は返す必要があります。operator new()noexceptnullptr
  2. nullptrが返された場合、式は式内の型のコンストラクターを呼び出しますnew。この構築が例外で失敗した場合、呼び出されたoperator delete()一致するoperator new()が呼び出され、その結果が返されoperator new()ます。

メモリ割り当ては失敗しないため、例外を取得する唯一のオプションは、型のコンストラクターからです。

于 2014-06-17T14:31:52.840 に答える