❥关于C++之引用
Posted itzyjr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了❥关于C++之引用相关的知识,希望对你有一定的参考价值。
引用的本质是指针
int rats = 101;
int& alias = rats;
int* prats = &rats;
——————————————————————————
alias <=> *prats <=> rats
&alias <=> prats <=> &rats
alias和*prats都可以同rats互换,&alias和prats都可以同&rats互换。从这一点来说,引用看上去很像伪装表示的指针。
也就是说:
int & alias = rats;
实际上是下述代码的伪装表示:
int * const pr = &rats;// 【指针常量】
由于pr是指针常量(指向不能变,所指值能变),所以pr所指地址不变,即一直跟踪rats,能通过pr改变rats的值,直接改变rats的值也同步到(*pr),所以和引用的本质是一样的。
引用也可以再赋值,引用效忠的对象也可再赋值,但总之引用是作为别名一直效忠于rats变量,不易主!
引用是引用的对象的别名!
int rats;
int& rodents = rats; // 使rodents成为rats的别名
引用更接近指针常量,必须在创建时进行初始化,一旦与某个变量关联起来,就将一直效忠于它(不易主)。——地址与地址上存的值总相同。
假设程序员试图这样做:
int rats = 101;
int* pt = &rats;
int& rodents = *pt; // 一直效忠rats
int bunnies = 50;
pt = &bunnies;
将rodents初始化为*pt使得rodents指向rats。接下来将pt改为指向bunnies,并不能改变这样的事实,即rodents引用的是rats。
下图直观演示了按值传递与按引用传递的区别:
示例:用三种方式,交互两个int值
#include <iostream>
void swapr(int& a, int& b); // a, b are aliases for ints
void swapp(int* p, int* q); // p, q are addresses of ints
void swapv(int a, int b); // a, b are new variables
int main()
using namespace std;
int wallet1 = 300;
int wallet2 = 350;
cout << "wallet1 = $" << wallet1;
cout << " wallet2 = $" << wallet2 << endl;
cout << "Using references to swap contents:\\n";
swapr(wallet1, wallet2); // pass variables
cout << "wallet1 = $" << wallet1;
cout << " wallet2 = $" << wallet2 << endl;
cout << "Using pointers to swap contents again:\\n";
swapp(&wallet1, &wallet2); // pass addresses of variables
cout << "wallet1 = $" << wallet1;
cout << " wallet2 = $" << wallet2 << endl;
cout << "Trying to use passing by value:\\n";
swapv(wallet1, wallet2); // pass values of variables
cout << "wallet1 = $" << wallet1;
cout << " wallet2 = $" << wallet2 << endl;
return 0;
void swapr(int& a, int& b)
int temp;
temp = a;
a = b;
b = temp;
void swapp(int* p, int* q)
int temp;
temp = *p;
*p = *q;
*q = temp;
void swapv(int a, int b)
int temp;
temp = a;
a = b;
b = temp;
wallet1 = $300 wallet2 = $350 <<原始数据
Using references to swap contents:
wallet1 = $350 wallet2 = $300 <<值被交换了
Using pointers to swap contents again:
wallet1 = $300 wallet2 = $350 <<值又被交换了
Trying to use passing by value:
wallet1 = $300 wallet2 = $350 <<交换失败
int main()
double x = 3.0;
cout << cube(x);
cout << " = cube of " << x << endl;
cout << refcube(x);
cout << " = cube of " << x;
return 0;
double cube(double a)
a *= a * a;
return a;
double refcube(double& ra)
ra *= ra * ra;
return ra;
27 = cube of 3
27 = cube of 27
为何要返回引用:
计算关键字return后面的表达式,并将结果返回给调用函数。从概念上说,这个值被复制到一个临时位置,而调用程序将使用这个值。
double m = sqrt(16.0);
cout << sqrt(25.0);
在第一条语句中,值4.0被复制到一个临时位置,然后被复制给m。在第二条语句中,值5.0被复制到一个临时位置,然后被传递给cout。
dup = accumalate(team, five);
如果accumulate()返回一个结构,而不是指向结构的引用,将把整个结构复制到一个临时位置,再将这个拷贝复制给dup。但在返回值为引用时,将直接把team复制到dup,其效率更高。
返回引用时最重要的一点是,应避免返回函数终止时不再存在的内存单元引用。应避免编写下面的代码:
const free_throws & clone2(free_throwns & ft)
free_throwns newguy; // first step to big error
newguy = ft; // copy info
return newguy; // return reference to copy
该函数返回一个指向临时变量(newguy)的引用,函数运行完毕后它将不再存在。同样,也应避免返回指向临时变量的指针。
为避免这种问题,最简单的方法是,返回一个作为参数传递给函数的引用。作为参数的引用将指向调用函数使用的数据,因此返回的引用也将指向这些数据。如下代码就是这样做的:
free_throws& accumulate(free_throws& target, const free_throws& source)
target.attempts += source.attempts;
target.made += source.made;
return target;
示例:不注意上面要避免的后果:
int& test(int&);
int main()
int x = 6;
int& y = test(test(x));// test()函数运行完后返回的临时引用消失!因为临时引用无变量承载!
cout << y;
return 0;
int& test(int& i)
int tmp = 2 * i;// 局部临时变量
return tmp;// 块结束后,tmp变量被系统回收消失
有些系统或IDE输出:
-1717986920
有些报错:
Segmentation fault
另一些报错:
warning: reference to local variable 'tmp' returned [-Wreturn-local-addr]
当返回值是引用类型时,会返回该变量的地址。当返回值不是引用型时,编译器会专门给返回值分配出一块临时内存。
总之,绝不能将一个指向局部变量的引用类型值作为函数的返回值!
同样,将一个指向局部变量的指针作为函数的返回值是也有问题的!
程序试图引用已经释放的内存,就是大问题。
将const用于引用返回类型及参数:
避免在设计中添加模糊的特性,因为模糊特性增加了犯错的机会。
accumlate(dup, five) = four;// 直接将函数返回的引用赋值!
假设您要使用引用返回值,但又不允许执行像给accumulate()赋值这样的操作,只需将返回类型声明为const
引用:
const free_throwns & accumlate(free_throwns & target, const free_throwns & source);
参数source类型也声明为const,让它成为“只读”。
当然,有时省略const确实有道理,在讨论的重载运算符<<就是一个这样的例子。
以上是关于❥关于C++之引用的主要内容,如果未能解决你的问题,请参考以下文章