Google C++プログラミング仕様でのレプリケーション構造関数と付与演算子の無効化


Google C++プログラミング仕様では、次の説明があります.
                         ;          
DISALLOW_COPY_AND_ASSIGN。 


  :                  (         )。 


  :                ,STL           、   。 


  :C++                  bugs   。          
     ,       ,             ,             
 。 

具体的には明らかにされていないが、今日は『More Effective C+』を見て、この問題を考え直した.
コンストラクション関数のコピーを無効にする理由は、次の2つです(以下を含むが、これらに限定されません).
1.時間がかかる
    継承階層が深くなるとオブジェクトが大きくなり、浅いレプリケーションを採用すると、速度が速くなりますが、メモリの漏洩や野ポインタの発生などのリスクがあります.深いコピーを採用すると、速度がかなり遅くなります.割り当て演算子も同じです.
2.安全でない
    付与演算子を使用する場合は、次の例を考慮します(読みやすいように、関数の定義とクラスの定義を一緒にしました).
#ifndef _HUMAN_H
#define _HUMAN_H

#include <cstdio>

class Human {
public :
  Human &operator=(const Human &rhs){
    printf("Human &operator=(const Human &rhs)
"); return *this; } }; class Male : public Human{ public : Male &operator= (const Human &rhs) { printf("Male &operator= (const Human &rhs)
"); return *this; } Male &operator=(const Male &rhs) { printf("Male &operator=(const Male &rhs)
"); return *this; } }; class Female : public Human { public : Female &operator= (const Human &rhs) { printf("Female &operator= (const Human &rhs)
"); return *this; } Female &operator=(const Female &rhs) { printf("Female &operator=(const Female &rhs)
"); return *this; } }; #endif // _HUMAN_H

次のmain関数を実行するとき:
int main() {
  Human *male1 = new Male();
  Human *male2 = new Female();

  *male1 = *male2;

  return 0;
}

呼び出されたのはHuman &operator=(const Human &rhs)このレプリケーション演算子.ベースクラスの付与演算子を呼び出すと、コピーされるのはベースクラスの部分だけで、本当の派生クラスの部分はコピーされません.これは私たちの意味に合いません.
付与演算子を虚関数として宣言すると、ベースクラスの 
virtual Male &operator= (const Human &rhs).この動作は私たちの意味とは異なり、呼び出しを望んでいます.
virtual Male &operator=(const Male &rhs).これを実現するには実際には可能ですが、一定の時間がかかります.呼び出した関数でdynamic_を使用するcastは、入力されたパラメータの動的タイプがベースクラスであるか派生クラスであるかを知ることができ、正しい付与演算子を選択します.でもdynamic_castの時間効率は本当によくありません.特に継承階層が深くなったときです.
以上のように、タイプを定義するときに、必要でない場合は、付与演算子とレプリケーション構造関数をできるだけ無効にします.代替として、このようなベースクラスを宣言し、そのベースクラスを継承することができます.
class NoCopyAndAssign {
public :
  NoCopyAnd *clone() const = 0;
private :
  NoCopyAndAssign(const NoCopyAndAssign &);
  void operator=(const NoCopyAndAssign &);
};

cloneでコピーした要素を指すポインタを返すといいです.もっと安全にしたいなら、戻ってきたポインタをauto_に包装してください.ptrタイプまたは他のスマートポインタタイプ.