46

boost / shared_ptr.hppを読んでいるときに、次のコードを見ました。

//  generated copy constructor, destructor are fine...

#if defined( BOOST_HAS_RVALUE_REFS )

// ... except in C++0x, move disables the implicit copy

shared_ptr( shared_ptr const & r ): px( r.px ), pn( r.pn ) // never throws
{
}

#endif

ここで、「生成されたコピーコンストラクタ、デストラクタはC ++ 11を除いて問題ありません、移動は暗黙的なコピーを無効にします」というコメントはどういう意味ですか?C ++ 11でこの状況を防ぐために、常に自分でコピーコンストラクターを作成しますか?

4

2 に答える 2

118

私はそれが正確でユーモラスであることがわかったので、ildjarnの答えを支持しました。:-)

OPが標準でそう言っている理由を知りたいと思うかもしれないという質問のタイトルのために、私は別の答えを提供しています。

バックグラウンド

C++ は暗黙のうちにコピー メンバーを生成しました。そうでなければ、C との互換性が非常に低く、1985 年にまだ誕生していなかっただろうからです。 .

そうは言っても、暗黙的に生成されたコピー メンバーは「悪魔との取引」に似ています。それらがなければ C++ は生まれませんでした。しかし、かなりの数のインスタンスで誤ったコードを静かに生成するという点で、それらは悪です。C++ 委員会は愚かではありません。彼らはこれを知っています。

C++11

C++ が誕生し、成長して成功を収めた今、委員会は次のように言いたいと思います。暗黙的にコピー メンバーを生成することはもうありません。彼らはあまりにも危険です。暗黙的に生成されたコピー メンバーが必要な場合は、その決定をオプトインする必要があります (オプトアウトするのではなく)。しかし、これを行うと壊れてしまう既存の C++ コードの量を考えると、それは自殺行為に等しいでしょう。非常に正当化される大きな後方互換性の問題があります。

したがって、委員会は妥協点に達しました。移動メンバーを宣言する場合 (従来の C++ コードでは実行できません)、既定のコピー メンバーが間違ったことを行う可能性が高いと想定します。必要に応じてオプトイン ( =default) します。または、自分で書きます。それ以外の場合、それらは暗黙的に削除されます。移動のみのタイプを持つ世界でのこれまでの経験から、このデフォルトの位置が実際には非常に一般的に望ましいものであることが示されています (例: unique_ptrofstreamなどfuture)。そして、オプトインの費用は、実際には非常にわずか= defaultです。

楽しみにしている

委員会は次のようにも言いたいと思います。デストラクタを作成した場合、暗黙のコピー メンバが間違っている可能性が高いため、それらを削除します。これが C++98/03 の「3 つのルール」です。ただし、それでも多くのコードが壊れます。ただし、委員会は C++11 で、ユーザー宣言のデストラクタを提供する場合、コピー メンバーの暗黙的な生成は非推奨であると述べています。つまり、この機能は将来の標準で削除される可能性があります。そして、いつの日か、コンパイラがこの状況で「非推奨の警告」を発行し始める可能性があります (標準では警告を指定できません)。

結論

C++ は何十年にもわたって成長し、成熟してきました。つまり、あなたの父親の C++ は、あなたの子供の C++ に対処するために移行する必要があるかもしれません。これはゆっくりとした段階的なプロセスであるため、手を上げて別の言語に移植することはありません。しかし、たとえ遅くても、それは変化です。

于 2012-06-29T02:15:27.187 に答える
31

C++ 標準がそう言っているので – §12.8/7:

クラス定義でコピー コンストラクターが明示的に宣言されていない場合は、暗黙的に宣言されます。クラス定義でムーブ コンストラクターまたはムーブ代入演算子が宣言されている場合、暗黙的に宣言されたコピー コンストラクターは deleted として定義されます。それ以外の場合は、デフォルトとして定義されます。クラスにユーザー宣言のコピー代入演算子またはユーザー宣言のデストラクタがある場合、後者のケースは推奨されません。したがって、クラス定義については

struct X {
    X(const X&, int);
};

コピー コンストラクターが暗黙的に宣言されています。ユーザーが宣言したコンストラクターが後で次のように定義されている場合

X::X(const X& x, int i =0) { /* ... */ }

X のコピー コンストラクターの使用は、あいまいさのために形式が正しくありません。診断は必要ありません。

(私のものを強調してください。)

于 2012-06-29T01:45:09.373 に答える