c++必知必会-3
条項5:参照はポインタではなく別名です
参照とポインタの違い:1、空の参照は存在しません;2、すべての参照を初期化する3、1つの参照は常に初期化に使用されるオブジェクトを指します.
注:一般的な参照は関数のパラメータに使用され、constを追加します.他の場所では、私は一般的にポインタを使用します.
一部のコンパイラでは、空の参照を明確に作成する試みをキャプチャできます.
しかし、コンパイラは、空の参照を作成する試みをそれほど明らかに検出できないため、実行中に未定義の動作が発生する可能性があります.
getAnEmployeeが空のポインタを返す場合、その後のコードの動作は定義されていません.この例では、getAnEmployeeが返す結果を格納するためにポインタを使用することが望ましい.
1つの参照が初期化されて特定のオブジェクトを指すと、その参照は後で他のオブジェクトを指すことはできません.リファレンスのライフサイクル全体で、リファレンスはそのオブジェクトを初期化するためにバインドされます.実際には、参照が初期化されると、そのオブジェクトの別名が初期化されます.このエイリアス(Alias)アトリビュートを使用すると、参照は常に関数パラメータの優れた選択になります.次のswap関数テンプレートでは、パラメータaおよびbは呼び出した実パラメータに渡される別名です.
2 D配列の特定の要素を設定する関数を考えてみましょう.
ただし、定数への参照は次のとおりです.
定数を指す参照が1つのフォント値で初期化されると、参照は実際には「フォント値で初期化」の一時的な位置を指すように設定されます.したがって、cdは本当に文字面値12.3を指すのではなく、12.3で初期化されたdoubleタイプの一時変数を指す.greetingリファレンスはaddの呼び出しに対して返される無名の一時string値を指す.一般に、このような一時オブジェクトは、作成された式の最後に破棄されます(正確には、役割ドメインを離れ、構造関数が呼び出されます).しかし、このような一時オブジェクトが定数を指す参照を初期化するために使用される場合、これらの一時オブジェクトは、参照がそれらを指す間ずっと存在します.
参照とポインタの違い:1、空の参照は存在しません;2、すべての参照を初期化する3、1つの参照は常に初期化に使用されるオブジェクトを指します.
注:一般的な参照は関数のパラメータに使用され、constを追加します.他の場所では、私は一般的にポインタを使用します.
一部のコンパイラでは、空の参照を明確に作成する試みをキャプチャできます.
Employee &anEmployee = *static_cast<Employee*>(0); // !
しかし、コンパイラは、空の参照を作成する試みをそれほど明らかに検出できないため、実行中に未定義の動作が発生する可能性があります.
Employee *getAnEmployee();
//...
Employee &anEmployee = *getAnEmployee(); //
if( &anEmployee == 0 ) //
getAnEmployeeが空のポインタを返す場合、その後のコードの動作は定義されていません.この例では、getAnEmployeeが返す結果を格納するためにポインタを使用することが望ましい.
Employee *employee = getAnEmployee();
if( employee ) //...
1つの参照が初期化されて特定のオブジェクトを指すと、その参照は後で他のオブジェクトを指すことはできません.リファレンスのライフサイクル全体で、リファレンスはそのオブジェクトを初期化するためにバインドされます.実際には、参照が初期化されると、そのオブジェクトの別名が初期化されます.このエイリアス(Alias)アトリビュートを使用すると、参照は常に関数パラメータの優れた選択になります.次のswap関数テンプレートでは、パラメータaおよびbは呼び出した実パラメータに渡される別名です.
template <typename T>
void swap( T &a, T &b ){
T temp(a);
a = b;
b = temp;
}
//...
int x = 1, y = 2;
swap( x, y ); // x == 2, y == 1
以上のswapの呼び出し期間全体において、aはxの別名であり、bはyの別名である.参照が指すオブジェクトに名前がなくてもよいので、参照は名前のないオブジェクトに便利な名前を付けるために使用できます.int grades[MAX];
//...
swap( grades[i], grades[j] );
2 D配列の特定の要素を設定する関数を考えてみましょう.
inline void set_2d( float *a, int m, int i, int j ) {
a[i*m+j] = a[i*m+j] * a[i*m+j] + a[i*m+j]; // !
}
// , 。
は参照バージョンを採用しており、所望の機能を実現することができる.inline void set_2d( float *a, int m, int i, int j ) {
float &r = a[i*m+j];
rr = r * r + r;
}
非常に多くの参照は、文字値または一時値で初期化できません.double &d = 12.3; // !
swap( std::string("Hello"), std::string(", World") ); // !
ただし、定数への参照は次のとおりです.
const double &cd = 12.3; // OK
template <typename T>
T add( const T &a, const T &b ) {
return a + b;
}
//...
const std::string &greeting
= add(std::string("Hello"),std::string(", World")); // OK
定数を指す参照が1つのフォント値で初期化されると、参照は実際には「フォント値で初期化」の一時的な位置を指すように設定されます.したがって、cdは本当に文字面値12.3を指すのではなく、12.3で初期化されたdoubleタイプの一時変数を指す.greetingリファレンスはaddの呼び出しに対して返される無名の一時string値を指す.一般に、このような一時オブジェクトは、作成された式の最後に破棄されます(正確には、役割ドメインを離れ、構造関数が呼び出されます).しかし、このような一時オブジェクトが定数を指す参照を初期化するために使用される場合、これらの一時オブジェクトは、参照がそれらを指す間ずっと存在します.