4

通常の左辺値参照を一時オブジェクトにバインドできないことがよくあります。そのため、クラス A のメソッドが、コピーを必要としない場合に const A& をパラメーターとして受け取ることがよくあります。ただし、そのような構成は完全に合法です。

double& d = 3 + 4;

一時オブジェクト 3 + 4 を参照 d にバインドするのではなく、オブジェクト 3 + 4 で参照を初期化するためです。変換または sth (つまり、別の一時オブジェクト) を使用して一時オブジェクトから取得したオブジェクトを使用して初期化されます。この場合、次のことがわかります。

int i = 2;
double & d = i;

i は double 型ではなく、それを継承していないため、これは正しくありません。ただし、それは一時オブジェクトを参照にバインドできることを意味しますが、それは本当にバインドされているのでしょうか? 一時オブジェクトをパラメーターとしてコピーコンストラクターを使用して新しいオブジェクトを作成していませんか?

したがって、私が思うに、A& の代わりに const A& param を取るメソッドを持つことのポイントは、2 番目のケースでは、そのようなメソッドがタイプ A の一時オブジェクトをパラメータとして取ることができないということではなく (そうなるため)、それにはコピーが含まれるためです。コンストラクター (パラメーターが型 A であるかのように)。私は正しいですか?

4

5 に答える 5

7

まず、他の人が言ったように、double& d = 3 + 4; 正当な C++ではありません。コンパイラがそれを受け入れ、C++ をコンパイルしていると主張する場合、それはコンパイラのエラーです。-std=c++98(ほとんどの C++ コンパイラは、g++ の場合など、特別なオプションを指定しない限り、C++ をコンパイルするとは主張しないことに注意してください。)

第二に、このルールの動機は経験に由来します。次の例を検討してください。

void
incr( int& i )
{
    ++ i;
}

unsigned x = 2;
incr( x );  //  Implicit conversion of unsigned to int
            //  creates a temporary.
std::cout << x << std::endl;
            //  and x is still equal 2 here.

参照の元の実装には、この制限はありませんでした。一時的に参照を初期化できます。実際の経験から、これはエラーが発生しやすいことがわかったため、const への参照を必要とする制限が導入されました。(1988 年か 1989 年頃なので、今日、コンパイラが強制しないという言い訳はありません。)

また、テンポラリを const 参照にバインドすると、テンポラリの寿命が延びるという話をよく耳にすることに注意してください。これは非常に誤解を招きやすいです: 参照を初期化するためにテンポラリを使用すると、(特定の例外を除いて) テンポラリの存続期間が延長されますが、この参照が他の参照を初期化するために使用されている場合、テンポラリもそれらの参照にバインドされているにもかかわらず、存続期間は延長されません。

于 2011-05-05T13:24:11.110 に答える
6

const &関数のパラメーター リストでのvs.の意味と目的について心配している場合&は、一時オブジェクトとはほとんど関係がないため、間違ったツリーを作成しているのではないかと心配しています。

void method( Object x );

Objectこれは、実引数からan をコピー構築します。関数内で行われた変更xは、関数が終了すると失われ、関数の引数は変更されません。

しかし、コピー構築のコストを払いたくありません。

void method( Object & x );

これは、実際の引数からan をコピー構築しませんが、x引数を参照します。つまり、関数内で行われた変更は、実際には引数自体に対して行われます。Objectx

ただし、メソッドの呼び出し元に、引数がどうなるかについて疑問を抱かせたくはありません。

void method( const Object & x );

これは、実引数からan をコピー構築せず、関数内変更できませんObjectx

コピー コンストラクターに料金を支払う必要はなく、呼び出し元に対して、引数が改ざんされないことを明確にします。

参照する変更可能なオブジェクトがないため、一時オブジェクトを2番目のバリアントに引数として渡すことはできません(unaperssonの回答を参照)。参照)、引数として一時的なものを渡すことはとにかく無意味です。

于 2011-05-05T09:53:24.290 に答える
1

double& d = 3 + 4;完全に合法ではありません。実際、標準に準拠したコンパイラでは受け入れられません。の結果3+4は一時的なタイプintです。そのため、const参照にのみバインドできます。

バインディング参照は本当にバインディングです。コピーは必要ありません。一時オブジェクトの寿命を延ばすだけです。

于 2011-05-05T09:50:40.767 に答える
0

参照は同じタイプの左辺値で初期化でき、3+4は左辺値ではありません。したがって、これは合法ではありません。MS VC ++コンパイラは、オブジェクトと同様の処理を許可しますが、これは標準ではありません。

于 2011-05-05T10:57:47.520 に答える
0
void f( int & n ) {
}

int main() {
    f( 1 + 2 );
}

コピーの作成は必要ありませんが、一時的なものはバインドされません。g++のエラーは次のとおりです。

タイプ'int'の右辺値からのタイプ'int&'の非定数参照の無効な初期化

于 2011-05-05T09:50:13.770 に答える