C++ 中級の章 - 3 と 5 の法則に従ってください。

1、3 対 5 ルール

3対5ルール、これはちょっとしたキャッチフレーズですが、3対5ルールが将来的に3対6ルールになるか、4対7ルールになるかは正直誰にもわかりません。とにかく、今は3対5ルールです。『c++Primer』の第 4 版では「3 の法則」と呼ばれ、第 5 版の 13.1.4 章では「3 と 5 の法則」と呼ばれています。
3対5の法則とは何ですか?別に言えば、3 つの規則は、C++ コンパイラがデフォルトでクラスの 3 つの基本的なコピー操作関数 (コピー コンストラクター、コピー代入演算子、およびデストラクター) を生成することを意味します。5 つのルールは、以前のルールに基づいて c++11 以降に提供された移動コンストラクターと移動代入演算子です。これらのクラスは通常、全体であり、そのうちの 1 つが必要な場合は、他のクラスも必要になります。
一般に C++ のプログラムを書く人はコンストラクタを書けばOKということが多いですが、例えば Qt が提供するカスタムクラスにはデストラクタがありません。ただし、デストラクターやコピー コンストラクターなど、そのうちの 1 つを定義するだけで、プログラムは正常に実行されます。はい、この想定外の状況を意図的に利用するケースは基本的には無いので問題ありません。(本にも書いてありますが、デストラクタのみ定義されていますが、コピーや代入操作は定義されておらず、シャローコピーによる同一ポインタの二次破壊の問題も発生します)。

2. 説明

1. 明示的に定義する必要があるデストラクターは、コピー コンストラクターと代入コンストラクターも定義する必要があります (または、そのうちの 1 つを定義し、他の 5 つは通常定義する必要があります)。上で分析したように、合成されたコピー シリーズ関数の場合、
浅いこのときの問題は、デストラクタが同じメモリ ポインタを複数回解放するという問題を引き起こし、これによって UB の問題も発生します。しかし実際には、基本的にこの動作はクラッシュしています。

class A
{
public:
    char * s_ = nullptr;

    A()
    {
        s_ = new char[10];
    }

    ~A()
    {
        delete s_;
    }
};

int main(void)
{
    A a;
    A b(a);

    return 0;
}

この問題は珍しいことではなく、コピー コンストラクターの説明に使用されているため、ほぼすべての C++ 入門書で同様の問題が言及されていますが、基本的にそれをデストラクターと関連付ける人はいません。
2. コピー操作が必要なクラスには代入操作も必要であり、その逆も同様です。
これは理解するのが簡単です。友達は一生を共に歩んでいきます (論理的な動作は一貫しています)。特にインタビューでは、この動作をコピー構築と呼ぶのか、代入操作と呼ぶのかをよく尋ねます。ここで確認すべき小さな質問があります。コピー コンストラクター パラメーターはなぜ参照でなければならず、const が必要なのでしょうか。前者は、非参照によって再帰ループとコンパイル エラーが発生するためであり、後者は必ずしも必要ではありませんが、常に行われてきました。
3. デストラクターは削除できません。
デストラクターを削除すると、スタック上のオブジェクトが解放されなくなるため、素晴らしい動作が生成されます。開発者がスタック上のこのオブジェクトを使用したくない場合は、次のようにすることができます。それをプライベートにします。つまり、このオブジェクトを動的に割り当て、関連するリソースを手動で解放できます。


4. クラスメンバに削除またはアクセスできないデストラクタ(またはコピー、代入)がある場合、クラス自身が自動的に削除済みとして定義されるデストラクタ(コピー、代入)を合成する これは、脆弱性が発生しないように定義ルールを厳しく制限することを意味します。自動合成コピー系列関数による。

class A
{
private:
  ~A();
};
class B
{
  A a;
};

5. クラスオブジェクトに const メンバや参照メンバがある場合、合成コピー代入操作は使用できませんが、
これは cv 修飾子のわかりやすい安全な扱いです。

3. まとめ

よく言われることですが、あなたの代わりに誰かがその重荷を背負っているのです。この文を C++ で使用するのは適切ではありませんが、おそらく同じ意味です。開発者が何もしない場合もありますが、基本的なコンパイルを確実に行うために、C++ 標準ではコンパイラーがバックグラウンドでいくつかの基本的なアクションを完了することを依然として要求しています。そして、標準が発展するにつれて、これらのことは増加する可能性があります。C++11 で導入されたモバイル構造を見てください。不変のものは何もありません。現在をより良く生きたいなら、変わらなければなりません。これが王道です。
先週、偉い人の名前を間違えてしまい、それが自分のジョークだったことが判明した。間に合うように指摘してくれた兄弟たち全員に感謝したいと思います。これらの兄弟は、
もっと水を飲み、もっと運動する、グー・ペン、エマ、そして若い虫捕りのシャオペンがあなたに挑戦します。
上記の友人に改めて感謝し、ウーロン事件についてお詫びします。

おすすめ

転載: blog.csdn.net/fpcc/article/details/132128887