これらは同じですか:
_int foo(bar* p) {
return p->someInt();
}
_
そして
_int foo(bar& r) {
return r.someInt();
}
_
NULLポインターの可能性を無視します。これらの2つの関数は、someInt()
が仮想であるか、bar
またはbar
のサブクラスが渡されるかに関係なく、機能的に同一ですか?
このスライスは何ですか:
_bar& ref = *ptr_to_bar;
_
C++参照は、ポインターを使用して実装される標準では意図的に指定されていません。参照は、変数へのポインタというよりも、変数への「同義語」に似ています。このセマンティクスは、ポインターが状況によっては過剰であることに気付くことができる場合に、コンパイラーに可能な最適化を開きます。
さらにいくつかの違い:
他の質問ではなく、他の質問では説明されていないポインタと参照の違いと、一方ではでき、もう一方ではできないすべての構文糖と可能性を無視します...それらは機能的にまったく同じです!どちらも関数を呼び出し、両方とも仮想関数を同様に適切に処理します。
いいえ、ラインはスライスされません。これは、ポインターによって指し示されたオブジェクトに参照を直接バインドしているだけです。
なぜ他のものを使用したいのかに関するいくつかの質問:
自分で違いを見つけようとする代わりに、知りたい場合はそれらに委任します。
参照は定数ポインターです。つまり、参照を変更して他のオブジェクトを参照することはできません。変更すると、参照オブジェクトの値が変更されます。
例:
int j = 10;
int &i = j;
int l = 20;
i = l; // Now value of j = 20
int *k = &j;
k = &l; // Value of j is still 10
はい、機能的には同じです。参照では、使用する前にオブジェクトに設定する必要があるため、無効なメモリへのNULLポインタまたはポインタを処理する必要はありません。
意味の違いを確認することも重要です。
私は長い間C++を使っていませんので、あなたの質問に本当に答えようとはしません(ごめんなさい)。しかし、Eric Lippertが excellent article を投稿しました。私はあなたが指し示すと思われるポインタ/参照についてです。
スライスについて一番下に隠されているあなたの2番目の質問に誰かが答えたかどうかはわかりません...それはスライスを引き起こしません。
スライスとは、派生オブジェクトが基本クラスオブジェクトに割り当てられた(コピーされた)場合です。派生クラスの特殊化は「スライス」されます。 objectがコピーされると言ったことに注意してください。コピー/割り当てられるポインタについてではなく、オブジェクト自体についてです。
あなたの例では、それは起きていません。参照の初期化で右辺値として使用されているBarオブジェクトへのポインターの参照を解除するだけです(その結果、Barオブジェクトになります)。用語が正しいかどうかわからない...
他の誰もが言及したように、実装では参照とポインタはほぼ同じです。いくつかの小さな警告があります:
参照にNULLを割り当てることはできません(shooshがこれを言及しました)。「未定義」または「無効な」参照値がないため、これは重要です。
一時変数をconst参照として渡すことができますが、一時変数にポインターを渡すことはできません。
たとえば、これは大丈夫です:
class Thingy; // assume a constructor Thingy(int,int)
void foo(const Thingy &a)
{
a.DoSomething();
}
void bar( )
{
foo( Thingy(1,2) );
}
しかし、ほとんどのコンパイラは文句を言うでしょう
void foo2( Thingy * a);
void bar2()
{
foo( &Thingy(1,2) );
}
void foo()
{
int a = 5;
// this may be slightly more efficient
int &b = a;
printf( "%d", ++b );
// than this
int *c = &a;
printf( "%d", ++(*c) );
}
同様に、 __ restrictキーワード は参照には適用できず、ポインターのみに適用できます。
参照を使用してポインター演算を行うことはできません。そのため、配列へのポインターがある場合、配列の次の要素はp + 1を介して取得できます。
機能は明らかに「同じ」ではありませんが、仮想的な動作に関しては同様に動作します。スライスに関しては、これは参照またはポインターではなく、値を扱う場合にのみ発生します。