これは、質問を説明するための簡略化された例です。
class A {};
class B
{
B(A& a) : a(a) {}
A& a;
};
class C
{
C() : b(a) {}
A a;
B b;
};
そのため、BはCの一部を更新する責任があります。lintを介してコードを実行し、参照メンバーについて lint#1725 と言いました。これは、デフォルトのコピーと割り当てを十分に公正に処理することについて述べていますが、デフォルトのコピーと割り当てはポインターでも悪いので、そこにはほとんど利点がありません。
裸のポインターは、そのポインターを削除する責任がある人について不確かに紹介するため、できる限り参照を使用しようとします。オブジェクトを値で埋め込むことを好みますが、ポインターが必要な場合は、ポインターを所有するクラスのメンバーデータでauto_ptrを使用し、オブジェクトを参照として渡します。
通常、ポインターがnullになったり変更されたりする可能性がある場合にのみ、メンバーデータでポインターを使用します。データメンバーの参照よりもポインターを好む他の理由はありますか?
参照は初期化された後に変更されるべきではないため、参照を含むオブジェクトは割り当て可能ではないというのは本当ですか?
参照メンバーは、クラスの実装が実行できることを制限するため(あなたが言及したように、代入演算子の実装を防ぐことを含む)、クラスが提供できるものには何の利点も提供しないため、参照メンバーを避けます。
問題の例:
.
演算子など)が、ポインタのように動作します(ぶら下げることができます)-たとえば Googleスタイルガイド がっかりさせます私の経験則:
オブジェクトが割り当てや比較などの他のものを許可することはめったにありません。 「Department」、「Employee」、「Director」などのオブジェクトを持つビジネスモデルを検討する場合、ある従業員が他の従業員に割り当てられるケースを想像するのは困難です。
したがって、ビジネスオブジェクトの場合、1対1および1対多の関係を、ポインターではなく参照として記述するのが非常に良いです。
そして、おそらく、1または0の関係をポインターとして説明してもかまいません。
したがって、「割り当てることはできません」と因数分解しません。
多くのプログラマーはポインターに慣れるだけであるため、参照の使用を避けるために引数を見つけます。
ポインターをメンバーとして持つと、使用する前に「念のため」のコメントを付けて、ユーザーまたはチームのメンバーがポインターを何度も何度もチェックするように強制されます。ポインターがゼロになる可能性がある場合、ポインターはおそらくフラグの一種として使用されますが、これはすべてのオブジェクトが独自の役割を果たさなければならないため、悪いことです。
いくつかの重要なケースでは、割り当て可能性はまったく必要ありません。これらは、多くの場合、スコープを離れることなく計算を容易にする軽量のアルゴリズムラッパーです。このようなオブジェクトは、常に有効参照を保持し、コピーする必要がないことを確認できるため、参照メンバーの主要な候補です。
そのような場合は、割り当て演算子(および多くの場合、コピーコンストラクター)を使用不可にしてください(boost::noncopyable
またはそれらをプライベートと宣言します)。
ただし、ユーザーptsはすでにコメントしているため、他のほとんどのオブジェクトには同じことが当てはまりません。ここで、参照メンバーの使用は大きな問題になる可能性があるため、通常は避ける必要があります。
誰もが一般的なルールを配布しているように見えるので、2つ提供します。
クラスメンバーとして参照を使用しないでください。私は自分のコードでこれを行ったことはありません(この規則に正しかったことを自分自身に証明することを除いて)。セマンティクスは複雑すぎるため、実際に参照が設計されたわけではありません。
基本型以外の関数にパラメーターを渡すとき、またはアルゴリズムがコピーを必要とするときは、常に、常に参照を使用します。
これらのルールはシンプルであり、私に代わるものでした。他のクラスメンバーとしてスマートポインター(ただし、auto_ptrではなく)を使用するルールを作成します。
はい: 参照は初期化された後に変更されるべきではないため、参照を含むオブジェクトは割り当て可能ではないというのは本当ですか?
データメンバーの経験則:
通常、ポインターがnullになったり変更されたりする可能性がある場合にのみ、メンバーデータでポインターを使用します。データメンバーの参照よりもポインターを好む他の理由はありますか?
はい。コードの可読性。ポインターを使用すると、メンバーが含まれているオブジェクトではなく、参照(皮肉なことに:))であることがより明確になります。昔ながらのやり方だと思う人もいますが、それでも混乱や間違いを防ぐだけだと思います。
誰があなたのクラスから派生するのか、彼らが何をしたいのかわからないので、参照データのメンバーに対してアドバイスします。彼らは参照されたオブジェクトを利用したくないかもしれませんが、有効なオブジェクトを提供することを強制した参照です。参照データメンバーの使用を停止するのに十分なだけ、これを自分で行いました。
質問を正しく理解したら...
ポインターの代わりに関数パラメーターとして参照:あなたが指摘したように、ポインターは、ポインターのクリーンアップ/初期化の所有者を明確にしません。ポインタが必要な場合は共有ポイントを優先します。これはC++ 11の一部であり、データの有効性がデータへのポインタを受け入れるクラスのライフタイムを通じて保証されない場合はweak_ptrです。 C++ 11の一部でもあります。関数パラメーターとして参照を使用すると、参照がnullでないことが保証されます。これを回避するには、言語機能を破壊する必要があります。ルーズキャノンコーダーは気にしません。
メンバー変数の参照:データの有効性に関しては上記と同じです。これは、ポイントされたデータが参照され、有効であることを保証します。
変数の有効性の責任をコード内の以前のポイントに移動すると、後のコード(この例ではクラスA)がクリーンアップされるだけでなく、使用する人にも明確になります。
少しわかりにくい例では(より明確な実装を探しています)、BがAのメンバーであるため、Bが使用するAはBの存続期間中保証されます。そして(おそらく)より明確です。
そして、念のために(これはコードのコンテキストでは意味をなさない可能性が低いため)、参照されていない非ポインターAパラメーターを使用する別の代替手段は、Aをコピーし、パラダイムを無用にします-Iこれを代替手段として意味するとは思わないでください。
また、これにより、参照されているデータを変更できないことも保証されます。この場合、ポインターを変更できます。 constポインターは、データへの参照/ポインターが変更可能でない場合にのみ機能します。
ポインターは、BのAパラメーターの設定が保証されていない場合、または再割り当てできる場合に役立ちます。そして時々、弱いポインターは実装には冗長すぎて、かなりの数の人がweak_ptrが何であるかを知らないか、単に嫌いです。
この答えをバラバラにしてください:)