引用—C++ primer

来源:互联网 发布:恶作剧软件下载 编辑:程序博客网 时间:2024/05/19 16:05

19.1 当引用定义完毕后,它就是另外一个变量的别名,以后使用变量和使用变量的别名效果一样。
int i = 1;
int &ri = i;
i = 2;
cout << i << " " << ri << endl; //输出:2 2
ri = 3;
cout << i << " " << ri << endl; //输出:3 3
19.2  当函数的参数为引用时:
1. 最简单的情况:
void f(int &i) { cout << i++ << endl; }
int main()
{
f(1); //error: 无法将参数1从int转为int &。原因见4
int i = 1;
f(i); //ok
}
2. 重载时会将引用考虑进去。但可能和非引用产生冲突:
void f(int &i) { cout << i++ << endl; }
void f(int i) { cout << ++i << endl; } //Ok. 重载f(int &) 
int main()
{
f(1); //Ok. 调用f(int)。(提醒:在上例1中这句话是错的)
int i = 1;
f(i); //error.对重载的调用不明确
int &ri = i;
f(ri); //error.对重载的调用不明确。
//虽然ri为i的一个引用,但使用起来却无法和i区分开来
}
3. 当引用碰到const:
int i = 1;
int &ri = i;
int const &const_ri = i; //ok. const_ri是一个int不变量的引用,其值不可改变
int & const const_ri2 = i; //ok. const_ri是一个int变量的不变引用,其值可以改变
//实际上:一个引用一旦定义(定义时必须初始化),它就只能是一个变量的引用,不能改成其它变量的引用
//这个定义和int &ri = i;语义是一样的
ri = 2; 
cout << i << " " << ri << " " << const_ri << " "<< const_ri2 << endl;  //输出: 2 2 2 2 
//注意:const_ri的值变了,因为它与其它变量都占据同一块内存
const_ri = 3;    //error.不能改变一个const量的值
const_ri2 = 4;    //ok.这是个有意思的的方。注意const_ri2与ri有相同的语义。
cout << i << " " << ri << " " << const_ri << " "<< const_ri2 << endl;  //输出: 4 4 4 4 
int j = ri;
j = 5;  //没有改变ri的值,因为j和ri占据两块不同的内存区域
所以,引用修饰符'&'应该与引用名放一起,不要在中间多余地加一个const。
int const &const_ri这个定义法很常见。
4. rvalue不能用来初始化引用变量,但可以初始化const引用变量:
rvalue:当常量作为参数调用函数时,常量为rvalue
当函数的返回值不是引用时,返回值为rvalue
看下面:
void test(int &i) { cout << i << endl; }
void test(int const &i) { cout << "const " << i << endl; }
int value(int i){ return i; }
int main()
{
test(1);  //输出:const 1
test(value(2)); //输出:const 2
int i = 3;
test(i);  //输出:3. 当没有test(int &)时调用test(int const &)
}
最重要的是:引用在使用前必须初始化,这是它和指针的最大区别。 
19.3 当引用碰到const和数组:
int ary[] = {1, 2, 3, 4};
int (&r_ary)[4] = ary;     //r_ary为ary的一个别名(或叫做引用)
//下面这句很糟
int (const &const_r_ary)[4] = ary;  //fatal error.这个导致严重的编译器内部错。
//一般的错误,编译器会指出程序错误的原因。但此时,好像编译器自己挂掉了,当然也就无法指出程序为什么错了。但是它指出了在哪条语句处出的错!
int (& const const_r_ary2)[4] = ary; //ok.但将const放在引用符'&'和引用名之间不起任何作用
//此const_r_ary2等效于r_ary
int const (&const_r_ary3)[4] = ary;  //ok.const_r_ary3是一个数组的引用,数组的成员不可改变
//推荐

数组的引用很奇怪,定义该引用时必须知道数组的大小,比如:
int ary;     //compile error:数组大小未知
int ary0[0];    //compile error:数组大小未知
int ary2[2];   //ok.
int (&ary0R)[];   //error:对零大小的数组的引用非法。
int (&ary2R)[] = ary2; //error:对零大小的数组的引用非法。
int (&ary2R)[2];  //error:引用必须初始化
int (&ary2R)[2] = ary2; //Ok!
int ary3[3];
int (&ary2R)[2] = ary3; //error:无法从int[3]转化为int (&)[2]
int (&ary2R)[sizeof(ary2) / sizeof(*ary2)] = ary2; //Ok

//下面看引用作为函数的参数时:
void f(int a[]) {} //Ok. a实际上是个指针
f(arg2);    //ok. arg2的长度为2,不限制参数的长度
void r(int (&ar)[]) {}  //error. 对零大小的数组的引用非法。
void r2(int (&ar)[2]) {} //Ok.
r2(ary2);     //Ok. 定义时引用颇多讲究,但使用起来两者可以互换
r2(ary2R);     //Ok.
r2(ary3);     //error:无法从int[3]转化为int (&)[2]

原创粉丝点击