4

次のコード( http://liveworkspace.org/code/5oact )が与えられます:

class Foo
 {
     public:
         Foo()
         {
             log(__PRETTY_FUNCTION__);
         }
         Foo(const Foo& other)
         {
             log(__PRETTY_FUNCTION__);
         }
         Foo& operator=(const Foo& other)
         {
             log(__PRETTY_FUNCTION__);
             return *this;
         }
         Foo(Foo&& other) noexcept
         {
             log(__PRETTY_FUNCTION__);
         }
         Foo& operator=(Foo&& other) noexcept
         {
             log(__PRETTY_FUNCTION__);
             return *this;
         }
         ~Foo(){}
 };

このようなクラスの使用:

std::vector<Foo> tt;

tt.emplace_back();
tt.emplace_back();
tt.emplace_back();
tt.emplace_back();

次の出力が得られます。

Foo::Foo()
Foo::Foo()
Foo::Foo(const Foo&)
Foo::Foo()
Foo::Foo(const Foo&)
Foo::Foo(const Foo&)
Foo::Foo()

カスタムデストラクタを削除すると、次の出力が得られます。

Foo::Foo()
Foo::Foo()
Foo::Foo(Foo&&)
Foo::Foo()
Foo::Foo(Foo&&)
Foo::Foo(Foo&&)
Foo::Foo()

デストラクタを宣言するときに、コンパイラが移動ではなくコピーコンストラクタを使用するのはなぜですか?移動操作はスローできないことを理解しています(noexceptコードからを削除すると、コンパイラはそれをまったく使用しません)が、デストラクタはそれと何の関係がありますか?

4

1 に答える 1

6

まず、間違ったnoexcept仕様を使用するコンパイラに問題があるようです。標準によると、12.4.3

例外仕様を持たないデストラクタの宣言は、暗黙の宣言と同じ例外仕様を持っていると暗黙的に見なされます。

デストラクタの暗黙の宣言は、noexceptすべてのメンバーとベースのデストラクタもnoexcept同様である場合です。したがって、明示的なデストラクタ宣言は次のようになります。

~Foo() noexcept {} // or:
~Foo() noexcept(true) {}

しかし、代わりにあなたのコンパイラはそれを次のように扱っています:

~Foo() noexcept(false) {}

第二に、デストラクタ例外指定が移動するかどうかの決定に影響を与える理由は、破壊が操作に関係しているためです。移動コンストラクター移動割り当て操作が決定に影響を与えるのと同様に、プロセスの途中で例外がスローされる可能性がある場合、移動は使用されません。noexcept

于 2013-02-17T19:23:30.937 に答える