私はこのガイドラインに重大な懸念を持っています。ガイドラインであってルールではないことを知っていても、まだ懸念があります。
std::complex<double>
、またはに似たユーザー作成クラスがあるとしますstd::chrono::seconds
。単なる値型です。リソースを所有していません。単純であることを意図しています。特別なメンバーではないコンストラクターがあるとしましょう。
class SimpleValue
{
int value_;
public:
explicit SimpleValue(int value);
};
さて、私もSimpleValue
デフォルトで構築可能にしたいので、別のコンストラクターを提供することでデフォルトのコンストラクターを抑制したので、その特別なメンバーを追加する必要があります:
class SimpleValue
{
int value_;
public:
SimpleValue();
explicit SimpleValue(int value);
};
人々がこのガイドラインと理由を覚えてしまうのではないかと心配しています: まあ、特別なメンバーを 1 つ提供したので、残りを定義または削除する必要があります。
class SimpleValue
{
int value_;
public:
~SimpleValue() = default;
SimpleValue();
SimpleValue(const SimpleValue&) = default;
SimpleValue& operator=(const SimpleValue&) = default;
explicit SimpleValue(int value);
};
うーん...移動メンバーは必要ありませんが、賢い人が私に言ったことに無頓着に従う必要があるので、それらを削除します:
class SimpleValue
{
int value_;
public:
~SimpleValue() = default;
SimpleValue();
SimpleValue(const SimpleValue&) = default;
SimpleValue& operator=(const SimpleValue&) = default;
SimpleValue(SimpleValue&&) = delete;
SimpleValue& operator=(SimpleValue&&) = delete;
explicit SimpleValue(int value);
};
CoreCppGuidelines C.21 によって、このような大量のコードが生成されるのではないかと心配しています。なぜそれが悪いのですか?いくつかの理由:
1.
これは、この正しいバージョンよりもはるかに読みにくいです。
class SimpleValue
{
int value_;
public:
SimpleValue();
explicit SimpleValue(int value);
};
2.
壊れてい ます。SimpleValue
関数から値によってa を初めて返そうとすると、次のようになります。
SimpleValue
make_SimpleValue(int i)
{
// do some computations with i
SimpleValue x{i};
// do some more computations
return x;
}
これはコンパイルされません。の削除されたメンバーへのアクセスに関するエラー メッセージが表示されますSimpleValue
。
私はいくつかのより良いガイドラインを持っています:
1.
コンパイラがいつ特別なメンバーをデフォルト化または削除するのか、およびデフォルト化されたメンバーが何をするのかを知っておいてください。
このチャートはそれを助けることができます:
このチャートが複雑すぎる場合は、理解できます。複雑です。しかし、少しずつ説明してくれると、対処しやすくなります。 このグラフを説明しているビデオへのリンクを付けて、1 週間以内にこの回答を更新できることを願っています。 説明へのリンクは、私が望んでいたよりも長く遅れた後です (私の謝罪): https://www.youtube.com/watch?v=vLinb2fgkHk
2.
コンパイラの暗黙のアクションが正しくない場合は、必ず特殊メンバーを定義または削除してください。
3.
非推奨の動作 (上のグラフの赤いボックス) に依存しないでください。デストラクタ、コピー コンストラクタ、またはコピー代入演算子のいずれかを宣言する場合は、コピー コンストラクタとコピー代入演算子の両方を宣言します。
4.
移動メンバーを削除しないでください。そうした場合、せいぜい冗長になります。最悪の場合、クラスが壊れます (SimpleValue
上記の例のように)。ムーブ メンバーを削除した場合、それは冗長なケースであり、読者にクラスを常に見直して、それが壊れたケースではないことを確認するように強制します。
5.
6 つの特別なメンバーのそれぞれに優しく愛情を込めて注意を払ってください。その結果、コンパイラーに処理を任せることになる場合でも (おそらくそれらを暗黙的に禁止または削除することによって)。
6.
特別なメンバーを一貫した順序でクラスの先頭 (明示的に宣言したいもののみ) に配置して、読者がそれらを検索する必要がないようにします。私は私のお気に入りのオーダーを持っています。あなたの好みのオーダーが違っていても構いません。私の好みの順序は、SimpleValue
例で使用した順序です。
このスタイルのクラス宣言について、より多くの理論的根拠を示した簡単な論文を次に示します。