参照される概念
人生において、私たちは私たち自身の特徴のためにあなたを別の名前と呼ぶことがよくあります。たとえば、あなたに精通している友人は通常あなたをシャオチェンと呼びます。C ++には、ニックネームに似た概念、つまり引用符もあります。
まず、誰かがあなたにニックネームを付けたように、参照は新しい変数を定義しないことを理解する必要がありますが、あなたはまだあなたであり、あなたは別の人にはなりません。同じことが参照にも当てはまります。コンパイラは参照用にメモリスペースを開きます。、それとそれが参照する変数は同じメモリスペースを共有します。
指示:
#include <iostream>
using namespace std;
//类型& 引用变量名(对象名) = 引用实体
void TestReft()
{
int a = 10;
int & ra = a;//定义引用类型(注意:引用类型必须和引用实体是相同类型的)
printf("%p\n", &a);
printf("%p\n", &ra);
}
int main()
{
TestReft();
return 0;
}
上記のプログラムを実行した結果は次のとおりです。変数aのアドレスと参照raのアドレスがまったく同じであることがわかります。
参照特性
1.参照は、定義時に初期化する必要があります。
これは、人生で誰かにエイリアスを与えることと同じです。エイリアスを与える人を知っている必要があり
ます。2。変数は複数の参照を持つことができます。
これは1つと同じです。人。多くのエイリアスは同じです
。3
。エンティティが参照されると、他のエンティティは参照できません。エイリアスが同じである人はたくさんいますが、2つの同一のエイリアスがC ++プログラムに表示され、コンパイラはそれを認識します。出てこないので許可されません。
使用するシーン
参照は、パラメーターまたは戻り値として使用できます。
1.パラメータを作成します
void Swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
2.戻り値を作成します
int& count()
{
static int n = 0;
n++;
return n;
}
関数が関数のスコープ外に戻る場合、返されたオブジェクトがシステムに戻されていない場合は、参照による戻りを使用できます。すでにシステムに戻されている場合は、次を使用する必要があります。値による戻り。
この文はどういう意味ですか?
最初に次の例を見てみましょう。
#include <iostream>
using namespace std;
int& Add(int a, int b)
{
int c = a + b;
return c;
}
int main()
{
int &ret = Add(1, 2);
Add(3, 4);
cout << "Add(1,2) is :" << ret << endl;
system("pause");
return 0;
}
演算結果:
おかしなことに、retの値を変更しなかったのですが、retの値が変わったという出力が出たので、上記のプログラムでretとcのアドレスを出力します。
#include <iostream>
using namespace std;
int& Add(int a, int b)
{
int c = a + b;
printf("c的地址是:%p\n", &c);
return c;
}
int main()
{
int &ret = Add(1, 2);
printf("ret的地址是:%p\n", &ret);
Add(3, 4);
//cout << "Add(1,2) is :" << ret << endl;
system("pause");
return 0;
}
演算結果:
cとretのアドレスを出力したところ、retは関数の戻り値cを参照しているため、アドレスがまったく同じであることがわかりました。関数を実行すると、ローカル変数cのスペースは関数本体はシステムによって取り戻されます。このとき、retは実際には不正なスペースを参照しますが、Add関数が終了すると、スタックフレーム内のガベージデータはクリーンアップされないため、retはスペース。2回目に行う場合この関数が呼び出されると、関数はスペース内の値を変更し、retの値も変更します。
値渡しと参照渡しの効率の比較
1.パラメータ
コードとして使用する場合:
#include <iostream>
using namespace std;
#include <time.h>
struct A{
int a[100000]; };
void TestFunc1(A a){
}
void TestFunc2(A &a){
}
void TestRefAndValue()
{
A a;
//以值作为参数
size_t begin1 = clock();
for (int i = 0; i < 100000; i++)
{
TestFunc1(a);
}
size_t end1 = clock();
//以引用作为参数
size_t begin2 = clock();
for (size_t i = 0; i < 100000; i++)
{
TestFunc2(a);
}
size_t end2 = clock();
//分别计算两个函数运算完成的时间
cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
int main()
{
TestRefAndValue();
system("pause");
return 0;
}
演算結果:
2。戻り値として
コード:
#include <iostream>
using namespace std;
#include <time.h>
struct A{
int a[100000]; };
A a;//值返回
A TestFunc1(){
return a; }
A& TestFunc2(){
return a; }
void TestReturnByReValue()
{
//以值作为返回类型
size_t begin1 = clock();
for (size_t i = 0; i < 100000; i++)
{
TestFunc1();
}
size_t end1 = clock();
//以引用作为返回类型
size_t begin2 = clock();
for (size_t i = 0; i < 100000; i++)
{
TestFunc2();
}
size_t end2 = clock();
//计算两个函数运算完成之后的时间
cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
int main()
{
TestReturnByReValue();
system("pause");
return 0;
}
演算結果:
参照とポインタの違い
1.文法の概念では、参照はエイリアスであり、独立したスペースはなく、スペースはその参照エンティティで使用されます。
2.参照はポインターの方法で実装されるため、実際には基礎となる実装の余地があります。
コード:
#include <iostream>
using namespace std;
int main()
{
int a = 10;
int& ra = a;
ra = 20;
int * pa = &a;
*pa = 20;
return 0;
}
参照とポインターの分解比較:
参照:
ポインター:
参照とポインターの違い:
1。参照は、定義時に初期化する必要があります
。2 。初期化中に参照がエンティティーを参照した後は、他のエンティティーを参照できません。任意のエンティティを指す場合、ポインタは任意の場所に
あります。3。NULL参照はありませんが、NULLポインタがあります
。4。sizeofでは、意味が異なり、参照の結果は参照タイプのサイズになりますが、ポインターは常にアドレス空間のバイト数にすることができます(32ビットプラットフォームで占有)(4バイト)
5。参照自己追加および参照エンティティは1増加しますポインター自己追加はタイプオフセットのサイズを指しますその後。
6.参照はポインタよりも使用するように、比較的安全です。