11

次のコード スニペットを考えてみましょう

void Test()
  {
  int x = 0;

  int& rx = x;
  int* px = &x;

  auto apx = px;    // deduced type is int*
  auto arx = rx;    // deduced type is int
  }

arxの推定型がであることを期待してポインタ型から類似性を引き出すことができますint&int、実際にはそうです。

それを支配する標準のルールは何ですか? その背後にある理由は何ですか?次のような場合、時々私はそれに引っ掛かります:

const BigClass& GetBigClass();
...
auto ref_bigclass = GetBigClass();   // unexpected copy is performed
4

2 に答える 2

14

使用auto&:

auto& ref_bigclass = GetBigClass();

参照は透過的であると想定されています。それらに対する操作は、参照するオブジェクトに対して行われ、参照自体を「取得」する方法はありません。

UPD: これは 7.1.6.4/6 でカバーされています:

declarator-id の型が 8.3 に従って決定されると、declarator-id を使用して宣言された変数の型は、テンプレート引数推論の規則を使用して初期化子の型から決定されます。

また、テンプレート引数の推定は 14.8.2.1/3 で定義されています。

テンプレート パラメーターの型 P が参照型の場合、P によって参照される型が型推定に使用されます。

PSこれは異なることに注意してくださいdecltype: decltype(rx)will yield int&type (7.1.6.2/4)。

于 2012-08-09T15:44:02.580 に答える
11

それについて考える最も簡単な方法は、それをテンプレートの実引数演繹と比較することです。

与えられた:

template<typename T>
void deduce(T) { }

あなたが呼び出す場合:

deduce(px);

テンプレート引数Tは次のように推定されint*ます

deduce(rx);

ではなく、Tとして推定されます。intint&

を使用すると、同じタイプが推定されautoます。

の推定型arxint&

その類推を行うには、かなり混乱した C++ 言語のモデルが必要です。Type@型と修飾子のように、構文的に類似した方法で宣言されているからといって、それらが同じように機能するわけではありません。ポインターは値、つまりオブジェクトであり、コピーして代入によって値を変更することができます。参照はオブジェクトではなく、何らかのオブジェクトへの参照です。参照をコピーしたり (参照をコピーすると参照対象がコピーされます)、変更したり (参照を割り当てると参照対象が変更されます) することはできません。ポインターを返す関数は値でオブジェクトを返します(問題のオブジェクトはポインター オブジェクトです) が、参照を返す関数 (あなたの のように) は参照GetBigClass()でオブジェクトを返します。. それらはまったく異なるセマンティクスであり、ポインターと参照の間の類推を描こうとすると失敗する運命にあります。

于 2012-08-09T16:09:23.977 に答える