この2つの機能は「パラメータを書けるか書けないか」が全然違うので、別の機能として同時に許してください。直感的に、そうあるべきです!
関数のオーバーロードは、呼び出し元が提供するパラメーターに基づいています。const
ここで、呼び出し元が値または非値を提供する可能性があることは事実ですconst
が、論理的には、呼び出された関数が提供する機能に違いはありません。検討:
f(3);
int x = 1 + 2;
f(x);
f()
これらの状況のそれぞれで異なることを行うと、非常に混乱します! このコード呼び出しのプログラマーはf()
、プログラムを無効にすることなく、パラメーターを渡す変数を自由に追加または削除して、同一の動作を合理的に期待できます。この安全で健全な動作は、例外を正当化したい出発点であり、実際に 1 つある -関数の ala がオーバーロードされたときに動作を変えることができる:
void f(const int&) { ... }
void f(int&) { ... }
だから、これはあなたが直感的でないと思うものだと思います.C++は、参照よりも非参照に対してより多くの「安全性」(単一の実装のみをサポートすることによって一貫した動作を強制する)を提供します.
私が考えることができる理由は次のとおりです。
const&
そのため、非パラメータの寿命が長くなることをプログラマが知っている場合、プログラマは最適な実装を選択できます。たとえば、以下のコードでは、T
内のメンバーへの参照を返す方が高速な場合がありますF
が、 がF
一時的な場合 (コンパイラが に一致する場合const F&
)、値による戻りが必要です。呼び出し元は、返された参照がパラメーターが存在する限り有効であることを認識する必要があるため、これは依然としてかなり危険です。
T f(const F&);
T&f(F&); // より適切な場合、戻り値の型は const& である可能性があります
const
次のような関数呼び出しによる -nessなどの修飾子の伝播:
const T& f(const F&);
T&f(F&);
ここでは、型のいくつかの (おそらくF
member-) 変数が、呼び出されたときのパラメーターの -ness に基づいて、または非-T
として公開されています。このタイプのインターフェースは、クラスを非メンバー関数で拡張したい場合 (クラスのミニマリストを維持するため、または多くのクラスで使用可能なテンプレート/アルゴを作成する場合) に選択できますが、考え方は のようなメンバー関数に似ています。ベクトル以外では許可されますが、ベクトルでは許可されません。const
const
const
f()
const
vector::operator[]()
v[0] = 3
const
const
値が値によって受け入れられると、関数が返されるときにスコープ外になるため、パラメーターの一部への参照を返し、その修飾子を伝達したいという有効なシナリオはありません。
必要な動作をハッキングする
参照の規則があれば、それらを使用して必要な種類の動作を取得できます-非 const-reference パラメーターを誤って変更しないように注意する必要があるため、次のようなプラクティスを採用することをお勧めします非 const パラメータ:
T f(F& x_ref)
{
F x = x_ref; // or const F is you won't modify it
...use x for safety...
}
再コンパイルの影響
なぜ言語が値渡しパラメータの -ness に基づくオーバーロードを禁止するのかという問題とは別に、宣言と定義で -ness のconst
一貫性を主張しないのはなぜかという問題があります。const
f(const int)
/ f(int)
... の場合、ヘッダー ファイルで関数を宣言している場合は、実装ファイルの後の定義に修飾子が含まれている場合でも、修飾子を含めないことをお勧めしますconst
。これは、メンテナンス中にプログラマーが修飾子を削除したい場合があるためです...ヘッダーから修飾子を削除すると、クライアントコードの無意味な再コンパイルがトリガーされる可能性があるため、同期を維持することを主張しない方がよいでしょう-実際、それがコンパイラがそうしない理由です'それらが異なる場合、エラーが発生します。関数定義で追加または削除するだけの場合const
、コードのリーダーが関数の動作を分析するときに constness を気にする可能性がある実装に近くなります。ヘッダーと実装ファイルの両方にある場合const
、プログラマーはそれを非const
const
クライアントの再コンパイルを避けるためにヘッダーを更新しないことを忘れるか、決定しない場合、プログラマーが現在の実装コードを分析しようとするときにヘッダーのバージョンを念頭に置いて間違ったコードを作成する可能性があるため、逆の場合よりも危険です。関数の動作についての推論。これはすべて非常に微妙な保守上の問題であり、実際には商用プログラミングにのみ関連しますが、それconst
がインターフェイスで使用しないというガイドラインの基礎となっています。さらに、インターフェイスから省略した方が簡潔です。これは、API を読み取るクライアント プログラマーにとってより適切です。