これは C++ 自体よりもコンピューター アーキテクチャに関する問題かもしれませんが、C++ のような言語でポインターを使用せずに理論的に参照渡しを実装できるかどうか疑問に思っていました。
以下に、同様の機能と構造を持つコードの例を 3 つ示します。
//Version 1: Uses global variable
#include <iostream>
int global_var = 0;
int increment(void) {return ++global_var;}
int main(void)
{
while (global_var < 100)
printf("Counter: %i\n", increment());
return 0;
}
//Version 2: Uses pass-by-pointer
#include <iostream>
int increment(int* ptr) {return ++(*ptr);}
int main(void)
{
int local_var = 0;
while (local_var < 100)
printf("Counter: %i\n", increment(&local_var));
return 0;
}
//Version 3: Uses pass-by-reference
#include <iostream>
int increment(int& ref) {return ++ref;}
int main(void)
{
int local_var = 0;
while (local_var < 100)
printf("Counter: %i\n", increment(local_var));
return 0;
}
私の推測では、最初のバージョンのインクリメント関数は、ポインターなしでグローバル変数に直接アクセスします。2 番目のバージョンは、ローカル変数を指す関数のスタック フレームにポインターを割り当て、間接的にアクセスします。クイック検索から、3 番目のバージョンは 2 番目のバージョンとまったく同じように (とにかく最適化する前に) 実装されているようです。出典:リファレンスは内部でどのように実装されていますか?
しかし、理論上(または実際には、コンパイラによる最適化後)、3 番目の関数は、ポインターなしで独自のスタック フレーム外のローカル変数に直接アクセスできますか? それとも、メモリ内の場所が静的であるため、その動作はグローバル変数に限定されますか?
ポインターの作成と逆参照には、少しの時間とメモリが必要だと思うので、これを尋ねます。十数回の参照を渡す深い再帰関数などでは、その時間とメモリが加算される可能性があります。
PS インライン関数についても具体的に言及する必要があります。これらの関数は新しいスタック フレームを生成することすらありません。つまり、バージョン 2 と 3 のアセンブリ コードは、関数がinline int increment(int*)
との場合に異なりますinline int increment(int&)
か? または、その場合、コンパイラはポインターを最適化して削除しますか?