C++ での定数参照と通常のパラメーターの受け渡し
この記事では、const 参照と通常のパラメーター受け渡しの違いについて説明します。
const 参照をよりよく理解するには、まず、値渡し、参照渡し、および const 参照渡しの違いを理解する必要があります。
C++ で値を渡す
パラメータ値を渡す前に、コンパイラはダミー変数を使用してメモリのコピーを作成し、その値が渡されます。
#include <bits/stdc++.h>
using namespace std;
void fun(int num) { num = num + 10; }
int main() {
int n = 30;
fun(n);
cout << n << endl;
}
出力:
30
パラメータ n
が fun()
関数を通過すると、コンパイラは n
にメモリコピーを作成します。コピーであるため、n
の元の値は関数によって変更されません。
ここで、2つの欠点があります。その値を変更することはできず、パラメータのコピーが作成され、メモリの浪費になります。
C++ での参照渡し
この方法は、値渡し法の欠点を排除します。ダミーパラメータを作成してその値を渡す代わりに、変数のエイリアスを渡します。
したがって、メモリの浪費はなく、変数のエイリアスが渡されるため、関数内の変数に加えられた変更はすべて反映されます。
#include <bits/stdc++.h>
using namespace std;
void fun(int &num) { num = num + 10; }
int main() {
int n = 30;
fun(n);
cout << n << endl;
}
n
の値はここで影響を受けます。
40
C++ で Const 参照を使用して渡す
これで、メモリを浪費したくない場合や変数の値を変更しない場合に、const 参照を使用できます。
#include <bits/stdc++.h>
using namespace std;
void fun(const int &num) { num = num + 10; }
int main() {
int n = 30;
fun(n);
cout << n << endl;
}
上記のコードは、num = num +10
が const 参照として渡されるため、コンパイルエラーをスローします。const であるため、パラメーターは読み取り専用になり、num
の値を変更することはできません。
出力:
[Error] assignment of read-only reference 'num'
参照が const 参照の場合、パラメーターの値は変更できないと述べましたが、微妙でありながら重大な違いがいくつかあります。
パラメータが const
参照であるが、渡されたパラメータが not const
であった場合、関数呼び出し中にパラメータの値が変更される可能性があります。
#include <bits/stdc++.h>
using namespace std;
void fun(const int &n) { const_cast<int &>(n) = 40; }
int main() {
int n = 30;
fun(n);
cout << n << endl;
}
渡されたパラメーターは const ではありませんでした。関数 fun
は、キャストの助けを借りてその値を変更できます。
出力:
40
const 参照を使用してパラメーターを渡す場合、逆参照の追加コストが含まれます。参照の最悪の局所性とコンパイラ最適化の機会はほとんどありません。
まとめ
構文-値渡し:
double fun(vector<double> my_vector); //pass by value
ここでの基になるオブジェクトまたはベクトルは、そのコピーコンストラクターを使用してコピーされます。新しいオブジェクトには追加のメモリが割り当てられており、すべての値とサブオブジェクトが個別にコピーおよび保存されます。
したがって、上記の関数はベクトルをコピーし、元のベクトル自体ではなく、そのベクトルのコピーに変更を加えます。オブジェクトまたはベクトルの受け渡しが膨大な場合、コピープロセスは非常に面倒になり、ストレージと CPU のサイクルが無駄になります。
構文-参照渡し:
double fun(vector<double> &my_vector); //pass by reference
基になるベクトルはコピーされず、ベクトル自体のメモリアドレスが渡されるため、関数によって行われた変更は元のベクトルに直接行われます。
これにより、新しいメモリが割り当てられず、(高価な)コピーコンストラクタが呼び出されないため、メモリと CPU の両方のサイクルが節約されます
。
構文-Const 参照による受け渡し:
double fun(const vector<double> &my_vector); //pass by const reference
上記の構文は、参照渡しに似ていますが、基になる値を変更できない点が異なります。これにより、オブジェクトの値をコピーおよび変更しないという問題が解決されます。
ここで、参照記号(&
)は、ベクトルをコピーしてはならないことを示し、キーワード const は、読み取り専用のベクトルを変更不可能にします。