目次
引用
1.はじめに
生活の中で、一部の学生にニックネームを付けることもあります.「張磊」を例にとると、彼を「張三師」と呼ぶことができます.このニックネームを呼ぶと、自然に「張磊」、「張三師」が思い浮かびます.は張磊の別名であり、引用は次の簡単な方法で理解できます。文法レベルでは、引用は別名です。
2. C++ でさらに厄介な演算子
* および C++ の & には複数の意味があり、使用条件が異なれば意味も異なります。
*
int *p = &a; /1.指针
a = a * b; /2.乘法
*p = 100; /3.指向
&
int c = a&b; /1.位运算 转换为二进制
int *p = &a; /2.取地址
int a = 100;
int & ar = a; /3.引用
3. 参照の定義
参照は、変数の新しい定義ではなく、既存の変数のエイリアスです. コンパイラは、参照変数用にメモリ空間を開かず、参照変数と同じメモリ空間を共有します.
形式は次のとおりです。
タイプ & 参照変数名 (オブジェクト名) = 参照エンティティ
ここでのスペースはオプションであることに注意してください。
- 次のように & 記号; の前後にスペースを入れることができます: int & ra=a;
- & 記号は、次のように型の横にあります。 int& ra=a;
- & 記号は、次のように参照名の横にあります。
int main()
{
int a =100; \\定义变量名
int b = a;\\将a的值赋给变量
int &c = a;\\引用 将c作为a的别名 c11中成为左值引用
return 0;
}
ここでは a と c という 2 つの名前を持つエンティティに相当し、この空間に新しい空間を開きません。
4. 引用の特徴
- 参照を定義するときに初期化する必要があります
- null 参照なし
- 二次引用のようなものはありません
- 変数は複数の参照を持つことができます (複数のエイリアスを持つ変数と同等であり、可能です)
説明:
int main()
{
int a = 10;
int& b = a;
int& x;
int& y = NULL;
int&& c = a;
}
要するに:
参照自体は変数ですが、この変数は単なる別の変数とエイリアスであり、メモリ空間を占有せず、ポインタではありません! ただの別名!
5. ポインタと参照の比較
例として swap 関数を使用して、
ポインターを使用して 2 つの整数値を交換してみましょう。
int my _swap (int*ap, int*bp)
{
assert(ap != NULL && bp != NULL);
int tmp = *ap;*ap = *bp;*bp = *ap;
}
int main()
{
int x = 10, y = 20;
my_swap{
&x,&y);
cout<< "x = " << x << " y = " << y << endl;
return 0;
}
参照を使用して 2 つのポインターを交換します。
void my_swap (int& a,int& b)
{
int tmp = a;a = b;
b = tmp;
}
int main ()
{
int x = 10, y = 20;my_swap(x,y) ;
cout << " x = " << x<< " y = " << y << endl;
return 0;
}
仮引数がポインタの場合:最初の文をアサートして空かどうかを判定しなければならず、ポインタを使う場合は注意が必要です:ワイルドポインター、ヌルポインタ、無効化ポインタ.
参照を使用する場合、NULL 参照がなく、null を判断する必要がなく、ポインターよりも安全です。
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
の<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
_
6. 参照とポインタの違い (強調)
1. 文法レベルの違い
- 文法規則に関して言えば、ポインター変数はインスタンス (変数またはオブジェクト) のアドレスを格納し、
参照はインスタンスのエイリアスです。 - プログラムはポインタ変数にメモリ領域を割り当てますが、参照にはメモリ領域を割り当てません。
int main()
{
int a = 10;
int* ip = &a;
int& b = a; \\b是a的别名 并没有分配新的空间
}
- 逆参照とは、ポインタを使用する前に「*」を追加することで、参照を直接使用できます。
int main()
{
int a = 10;
int* ip = &a;
int& b = a;
*ip = 100;//对于指针使用加“*”
b = 200; //引用不需要“*”
}
- ポインター変数の値は、異なるインスタンスのアドレスを格納するために変更できます。
参照は、定義時に初期化され、後で変更することはできません (他のインスタンスへの参照にすることはできません)。
int main()
{
int a = 10,b = 20;
int* ip = &a;
ip = &b ;
int& c = a;
c = b; //b的值给c实则是把b的值给a,将a的值改为20
}
- ポインター変数の値は空 (NULL、nullptr) にすることができ、null 参照はありません。
- ポインタ変数を仮パラメータとして使用する場合は、その有効性をテストする必要があります (NULL と判断する)
参照は NULL と判断する必要はありません。 - ポインター変数で「sizeof」を使用するとポインター変数のサイズが取得され、
参照変数で「sizeof」を使用すると変数のサイズが取得されます。
int main()
{
double dx = 10;
double* dp = &dx;
double& a = dx;
printf("sizeof(dp):%d\n", sizeof(dp));
printf("sizeof(a):%d", sizeof(a));
}
操作結果:
-
理論的には、ポインターのレベル数に制限はありませんが、参照のレベルは 1 つだけです。
つまり、参照への参照はありませんが、ポインターへのポインターは存在できます。 -
++参照には、++ポインタとは異なる効果があります。
たとえば、++ 操作に関しては、次のようになります。
int main()
(
int ar[5] = {
1,2,3,4,5 };
int* ip = ar; //数组首元素地址
int& b = ar[O]; //数组首元素的别名叫b
++ip; //由0下标的地址指向1下标的地址
++b; //由0下标指向1下标
}
- 参照に対する操作は、参照されるエンティティ (変数またはオブジェクト) に直接反応します。
ポインター変数に対する操作は、ポインター変数が次のエンティティー (変数またはオブジェクト) のアドレスを指し示すようにします。ポインター変数は、ポイントされたエンティティー (変数またはオブジェクト) の内容を変更するのではありません。
int main()
(
int ar[5] = {
1,2,3,4,5 };
int* ip = ar; //数组首元素地址
int& b = ar[O]; //数组首元素的别名叫b
++(*ip); //值由1>>2
(*ip)++; //所有表达式结束后 进行++
//有括号 先取ip的值与*结合 然后++为所指之物的++
int x = *ip++;
//没有括号 先将ip的值取出 与*结合 把所指之物取出(此时已与*结合完) 然后将ip取出进行++ ++后的值回写给ip 将值存储到x中
//通过()提高了优先级
}
-
関数内のローカル変数またはオブジェクトは、参照またはポインターによって返すことはできません。
変数の有効期間が関数の影響を受けない場合、アドレスを返すことができます
2. アセンブリ レベルでの相違点
アセンブリ レベルでは、参照はポインターですが、参照は通常のポインターではなく、ポインターの構文スロットであり、通常のポインターと見なすこともできます。
int main()
{
int a = 10;
int* ip = &a;
int& x = a;
*ip = 100;
x = 200;
}
7. 参考文献のその他の用途
- よく引用される:
定数参照は、実際には、通常の変数、定数、またはリテラル定数を参照できるユニバーサル参照です。
(1) 通常変数参照
int main()
{
int a = 10;
int & b = a;
const int& c = a;
b += 10;
a += 10;
c += 10;
return 0;
}
このエラーの問題の場合: c は変更できないため
(2) 参照定数
int main()
{
int a = 10;
const int b =20;
int& x = a;
int& y = b; //error 不安全
const int& y = b; //ok
const int& z =10; //ok
return 0;
}
(3) 文字定数の引用
リテラル定数を参照する場合は2段階に分かれますが、まず実定数リテラルを参照するのではなく、テンポラリを参照するテンポラリを定義します。
int main()
{
int a = 10;
const int& z =10; //ok
//int tmp =10;
//const int &z = tmp;
return 0;
}
- 配列参照
配列を参照するときは、配列のサイズがわかっている必要があります
int main()
{
int a = 10;
int b = 10;
int ar[5] = {
1,2,3,4,5 };
int& x = ar[0]; //ok
int(&x)[5] = ar; //ok 没有[5]无法编译通过
return 0;
}
- ポインター参照
参照は変数なので、ポインター変数にエイリアスを与えることもできます
int main()
{
int a = 100;
int *p = &a;
int * &rp = p;
cout << a << endl;
cout << *p << endl;
cout << *rp << endl; //这里为什么要将*放在前面,因为p的类型是 int * 作为一个整体哦!!
cout << p << endl;
cout << rp << endl;
getchar();
return 0;
}
/*
100
100
100
012FF84C
012FF84C
*/
ここでのポインター変数 p は、その参照 (エイリアス) rp とまったく同じであることがわかりました。ただし、参照の目的はポインターの目的と似ているため、通常、ポインターに別名を付ける必要はありません。