2

C++ をいじっているときに、代入演算子/オブジェクトのコピーに対する標準的なコンパイラの動作が面倒だということに気付きました。クラスのすべてのメンバーが定義済み/デフォルトのコピー/割り当て動作を持っている場合のデフォルトのコード生成を理解できますが、コンパイラーがポインターを愚かな方法でコピーするコードを生成するリスクを単一の警告なしで生成する理由がわかりません...この場合、なぜコンパイラはユーザーのために決定するのですか? デフォルトのポインターの書き換えがまったく意味のある状況は本当にありますか?

@編集:

これが炎の餌として閉じられる前に、私は怒鳴るつもりはなかったと指摘したいと思います. コメントで述べたように、3 のルールに例外があるかどうかも尋ねたいと思います。

4

6 に答える 6

3

コンパイラがポインタをばかげた方法でコピーするコードを生成するリスクを冒す理由がわかりません

メンバとしてポインタを持つクラスには何の問題もありませんし、これらのクラスを浅いコピーすることにも何の問題もありません。

厄介なのはリソースの所有権です。

ここでの本当の原因は動的メモリ割り当てであり、ポインター メンバーがありません。そして、これはただ 1 つの特定のケースです。その他には、ロック、ストリーム、接続などがあります...

指しているメモリがクラスによって所有されていない場合、違いはありません。たとえば、ファイル ストリームと同じです。クラスをコピーして、両方のコピーが同じストリームを参照することもできますが、いつストリームを閉じるのでしょうか。どのコピーがそれを閉じますか? (「コピーのどれがメモリを削除しますか?」)

3つのルールが有効になっていると、このことを徹底的に考えさせられます。

全体として、ポインターやストリーム、またはその他のリソースであるメンバーがある場所に警告を表示するのは非現実的だと思います-それらはたくさんあり、ほとんどは役に立たないでしょう。

于 2013-01-11T23:37:25.847 に答える
2

指摘されているものが問題のクラスによって所有されていない場合 (まったく珍しいことではありません)、浅いコピーがまさにあなたが望むものです。コンパイラは、所有権のセマンティクスが何であるかをクラス定義から判断できないため、1 つの妥当な推測を行います。つまり、すべてが浅いコピーであるということです。

クラスにポインターの所有権セマンティクスがある場合は、適切なスマート ポインター ( 、 など) を使用unique_ptrshared_ptrて所有権を文書化する必要があります。

于 2013-01-12T00:24:00.867 に答える
1

プレーン (またはダム) ポインターには、コピーと代入の動作が定義されています。

ポインターが常に所有権を示している場合は、スマートポインターを使用する必要があります。そうすれば、コピーと代入の振る舞いは、あなたが望むものになる可能性が高くなります (または、少なくともそうすることができます)。

于 2013-01-11T23:35:15.490 に答える
1

ほんの一例:
各ノードが子を所有するツリー データ構造がある場合、それらの子ポインターはスマート ポインターになりますが、親へのポインターを保持する場合は、生のポインターになります。それが指すものの寿命を管理していません。

于 2013-01-11T23:35:39.437 に答える
1

スピードとパワーのために。

ナイーブでないコピーには時間がかかる場合があります。これがプログラムの問題である場合、3 のルールをオプトアウトすることが非常に現実的です。

C++ へようこそ。あなたは自分が何をしているのかを知っていることが期待されています。

于 2013-01-11T23:38:26.830 に答える
0

この場合、なぜコンパイラはユーザーのために決定するのですか?

重要なのは、コンパイラが決定しないということです。それらはプログラマーに決定させます。とにかく、あなたは何を期待していますか?ディープコピーを作成しますか? それは正確には不可能です。次の点を考慮してください。

// This isn't necessarily "good" code, but it's legal
struct MyStruct
{
    void* p;
    const char* str;
};

MyStruct m1, m2;

m1.p = (void*)&m2;
m1.array = "Hello world!";
m2 = m1; // Now what do you expect to happen?

C++ は適切なコードを書くことを強制しないので、上記は完全に合法です。上記は適切なコードではありませんが、構造体でのポインターの一般的な使用例を示しています。m1に割り当てるときに、 のディープ コピーを作成することはできませんm2。上記がコンパイルに失敗するため、ディープコピーがデフォルトの動作である場合は最悪です。

于 2013-01-11T23:38:48.893 に答える