C++ での参照
この記事では、C++ で参照を使用する方法の複数の方法を示します。
C++ で& attr(optional) declarator
表記を使用して lvalue
参照を宣言する
参照は、オブジェクトの代替名を定義します。それらはそれ自体がオブジェクトではないため、参照の配列や参照へのポインターを持つことはできません。参照は既存のオブジェクトのみを参照し、これらのオブジェクトにバインドされます。これは、宣言後に変更が許可されないことを意味します。
さらに、参照を初期化する必要があり、参照名を使用して操作を実行すると、バインドされたオブジェクトが変更されます。後者の機能により、ポインターと非常によく似ていることに注意してください。対応するオブジェクトの値にアクセスするための逆参照表記なしで前者を通常の変数名として使用できることを除いて、参照をポインターの代替と見なすことができます。参照の動作を模倣したい場合は、指定された型への const
ポインターを宣言できます。後者は、値にアクセスするという表記を除いて、参照と同じ機能を備えています。
次のサンプルコードでは、変数 xr
が int
オブジェクトを表す x
への参照として宣言されています。宣言中に xr
が初期化されると、どのタイプの別のオブジェクトを参照するように再割り当てすることもできません。一方、xr
などの異なるエイリアス名を、それが参照する同じオブジェクトに定義できます。つまり、xrc
は const
修飾参照です。つまり、対応するオブジェクトの値にはアクセスのみが可能であり、エイリアス名を使用して変更することはできません。
#include <iostream>
using std::cout;
using std::endl;
int main() {
int x = 5;
int& xr = x;
const int& xrc = x;
xr *= xr;
// xrc *= x; Error
cout << "xr: " << xr << endl;
cout << "xrc: " << xrc << endl;
return EXIT_SUCCESS;
}
出力:
xr: 25
xrc: 25
次のコードスニペットに示すように、同じオブジェクトへの複数の参照を宣言できます。それでも、エイリアスのいずれかからの変更は同じオブジェクトに影響を与えることに注意する必要があります。
#include <iostream>
using std::cout;
using std::endl;
int main() {
int x = 5;
int& xr = x;
int& xrr = x;
xr *= xr;
xrr *= xrr;
cout << "xr: " << xr << endl;
cout << "xrr: " << xrr << endl;
return EXIT_SUCCESS;
}
出力:
xr: 625
xrr: 625
C++ で参照を使用して関数プロトタイプを実装する
参照は主に、よりクリーンな関数インターフェイスを提供するために使用されますが、C++ 言語は演算子のオーバーロード機能を提供し、表記はすべての演算子で同じである必要があるためです。言語に参照概念がない場合、後者は複雑になります。したがって、引数を取る必要のある演算子をポインターとして使用すると、++&x
のようになります。
値にアクセスするためにオブジェクトを取得する必要がある関数は、対応する引数を const
参照として指定でき、const
なしで変更が必要な場合もあります。たとえば、printVector
関数は std::vector
への const
参照を取り、要素を cout
ストリームに出力しますが、swapElements
は各要素を交換する必要があるため、定期的に参照する必要があります。
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
using std::cout;
using std::endl;
using std::setw;
using std::string;
using std::vector;
template <typename T>
void printVector(const vector<T> &vec) {
for (auto &i : vec) {
cout << i << "; ";
}
cout << endl;
}
template <typename T>
void swapElements(vector<T> &vec) {
for (auto iter = vec.begin(); iter < vec.end() - 1; ++iter) {
std::swap(*iter, *(iter + 1));
}
}
int main() {
vector<int> vec1 = {43, 5, 123, 94, 359, -23, 2, -1};
printVector(vec1);
swapElements(vec1);
printVector(vec1);
return EXIT_SUCCESS;
}
出力:
43; 5; 123; 94; 359; -23; 2; -1;
5; 123; 94; 359; -23; 2; -1; 43
const
のものを含む以前のすべての参照の例は、左辺値参照と呼ばれることに注意してください。これらの参照は、アクセスまたは変更した後に有効な値を保持する必要があるオブジェクトを参照するために使用されます。C++ 言語は、一時オブジェクトを参照するために使用される右辺値参照も提供します。
一時オブジェクトは、指定されたオブジェクトが再び使用されないことをプログラマーが想定しているものです。右辺値参照は、&& attr(optional) declarator
表記を使用して指定され、オブジェクトは左辺値参照と同様にアクセスされます。右辺値参照は、コンストラクターの移動や割り当ての移動などの効率的な操作を実装するために使用され、大きなオブジェクトの高価なコピーを回避します。