web-dev-qa-db-ja.com

言語設計の観点から、C ++の参照型は設計が間違っている

C++のすべてのプリミティブ型は参照型を除いてコピー割り当てが可能であるという事実に加えて、コピー割り当てが可能なセマンティクスが必要なコンテナーや言語のその他の部分ともうまく機能しません。私は個人的にこれが std::reference_wrapper 言語の制限を回避するために、後でその言語を導入する必要がありました。

振り返ってみると、C++の参照型は、最初に設計されたとき、よく考えられていなかったと結論付けることができますか?
言語設計の観点から、新しく導入された参照ラッパーのように動作するものとして定義されている必要がありますか?

2
John Z. Li

C++参照型はすぐには問題になりません。参照はオブジェクトではなく、オブジェクトのエイリアスにすぎません。これを念頭に置くと、多くの誤解がすぐに解決されます。コンテナにはオブジェクトが含まれているため、参照ではありません。参照のような動作だけでなく実際のオブジェクトも必要な場合は、ポインターまたはラッパーを使用してください。

ポインタが与えられた場合、参照は不要であると主張することができます。ただし、ポインターを使用するCコードと参照を使用するC++コードを比較すると、参照を使用すると言語の人間工学が大幅に向上しますが、多少の明示性が犠牲になります。参照は、C++のオブジェクトライフタイム/ RAIIの概念と中間値(lvalueとrvalueの参照を比較)とうまく統合され、関数呼び出しによって暗黙的に作成されます。対応するCコードは、より多くの&*、および->演算子を備えています。

Cのポインター減衰規則は、C++参照などの同様の言語の人間工学の問題に対処することに注意してください。ただし、ポインター減衰は、配列、文​​字列リテラル、および関数ポインターにのみ適用されます。 C++では、参照を使用して減衰を防ぐことができます。

CまたはC++と同じ空間にある新しい言語は、ポインターと参照をより類似させるか、どちらかを取り除く傾向があります。

  • Goにはポインターしかありませんが、状況によっては左辺値が自動的にポインターに変換され(たとえば、一部のメソッド呼び出しの場合)、ポインターが暗黙的に逆参照される場合があります(->演算子はありません)。
  • Rustには安全でないコードへのポインタがありますが、通常は参照のみを使用します。これらは所有権のセマンティクスに関してはC++参照に似ていますが、オブジェクトであるため、明示的に逆参照する必要がある場合があります。
  • JavaまたはC#のような言語は、明示的な参照またはポインタを完全に取り除きましたが、これはオブジェクトが値のセマンティクスを持たなくなったことを意味します。C#は、追加のパラメーター注釈(out-parametersまたはref- parameters)。ただし、これはC++の参照のユースケースの一部のみをサポートします。C#はユーザー定義の値の型(構造体)をサポートしますが、値のセマンティクスとC++のような参照セマンティクスC#は、安全でないコードのポインターをサポートします。
7
amon

C++ 定義しない カテゴリープリミティブ型

基本タイプを間違えている可能性があります。これは、voidstd::nullptr_t、およびさまざまな算術タイプのカテゴリです。これらは割り当て可能です(voidを除く)。

参照型は、複合型であり、ポインター、メンバーへのポインター、配列、関数、列挙型、およびクラス型と同じレベルの分類です。

配列と共通1、関数、およびそれらを割り当てることができないさまざまなクラス。

  1. 配列は本当に奇妙な配列です。他の割り当て不可のタイプは、オブジェクトではないか、作成者によって割り当てが削除されました
3
Caleth