博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入分析C++引用
阅读量:4612 次
发布时间:2019-06-09

本文共 4541 字,大约阅读时间需要 15 分钟。

下面是用的http://blog.csdn.net/shenlanzifa/article/details/40372915的一片文章。

关于引用和指针的区别的文章很多很多,但是总是找不到他们的根本区别,偶然在codeproject上看到这篇文章,觉得讲的挺好的,

所以翻译了下,希望对大家有帮助。

原文地址: http://www.codeproject.com/KB/cpp/References_in_c__.aspx

 

引言

      我选择写 C++ 中的引用是因为我感觉大多数人误解了引用。而我之所以有这个感受是因为我主持过很多 C++ 的面试,并且我很少从面试者中得到关于 C++ 引用的正确答案。

       那么 c++ 中引用到底意味这什么呢?通常一个引用让人想到是一个引用的变量的别名,而我讨厌将 c++ 中引用定义为变量的别名。这篇文章中,我将尽量解释清楚, c++ 中根本就没有什么叫做别名的东东。

 

背景

在 c/c++ 中,访问一个变量只能通过两种方式被访问,传递,或者查询。这两种方式是:

1. 通过值 访问 / 传递变量

2. 通过地址 访问 / 传递变量 – 这种方法就是指针

 

       除此之外没有第三种访问和传递变量值的方法。也就是个指针变量,它也拥有内存空间。最关键的是引用是一种会被编译器自动的指针。很难相信么?让我们来看看吧。。。

 

下面是一段使用引用的简单 c++ 代码

#include 
int main(){ int i = 10; // A simple integer variable int &j = i; // A Reference to the variable i j++; // Incrementing j will increment both i and j. // check by printing values of i and j cout<< i << j <

引用其实就是 c++ 中的指针常量。表达式   int &i = j; 将会被编译器转化成 int *const i = &j; 而引用之所以要初始化是因为 const 类型变量必须初始化,这个指针也必须有所指。下面我们再次聚焦到上面这段代码,并使用编译器的那套语法将引用替换掉。

#include 
int main(){ int i = 10; // A simple integer variable int *const j = &i; // A Reference to the variable i (*j)++; // Incrementing j. Since reference variables are // automatically dereferenced by compiler // check by printing values of i and j cout<< i << *j <

    读者一定很奇怪为什么我上面这段代码会跳过打印地址这步。这里需要一些解释。因为引用变量时会被编译器自动解引用的,那么一个诸如   cout << &j << endl; 的语句,编译器就会将其转化成语句   cout << &*j << endl;   现在 &* 会相互抵消,这句话变的毫无意义,而 cout 打印的 j 值就是 i 的地址,因为其定义语句为 int *const j = &i;

 

      所以语句 cout << &i << &j << endl; 变成了 cout << &i << &*j << endl; 这两种情况都是打印输出 i 的地址。这就是当我们打印普通变量和引用变量的时候会输出相同地址的原因。

 

      下面给出一段复杂一些的代码,来看看引用在级联 (cascading) 中是如何运作的。

#include 
int main(){ int i = 10; // A Simple Integer variable int &j = i; // A Reference to the variable // Now we can also create a reference to reference variable. int &k = j; // A reference to a reference variable // Similarly we can also create another reference to the reference variable k int &l = k; // A reference to a reference to a reference variable. // Now if we increment any one of them the effect will be visible on all the // variables. // First print original values // The print should be 10,10,10,10 cout<< i << "," << j << "," << k << "," << l <

下面这段代码是将上面代码中的引用替换之后代码,也就是说明我们不依赖编译器的自动替换功能,手动进行替换也能达到相同的目标。

#include 
int main(){ int i = 10; // A Simple Integer variable int *const j = &i; // A Reference to the variable // The variable j will hold the address of i // Now we can also create a reference to reference variable. int *const k = &*j; // A reference to a reference variable // The variable k will also hold the address of i because j // is a reference variable and // it gets auto dereferenced. After & and * cancels each other // k will hold the value of // j which it nothing but address of i // Similarly we can also create another reference to the reference variable k int *const l = &*k; // A reference to a reference to a reference variable. // The variable l will also hold address of i because k holds address of i after // & and * cancels each other. // so we have seen that all the reference variable will actually holds the same // variable address. // Now if we increment any one of them the effect will be visible on all the // variables. // First print original values. The reference variables will have * prefixed because // these variables gets automatically dereferenced. // The print should be 10,10,10,10 cout<< i << "," << *j << "," << *k << "," << *l <

         我们通过下面代码可以证明 c++ 的引用不是神马别名,它也会占用内存空间的。

#include 
class Test{ int &i; // int *const i; int &j; // int *const j; int &k; // int *const k; };int main(){ // This will print 12 i.e. size of 3 pointers cout<< "size of class Test = " << sizeof(class Test) <

结论

我希望这篇文章能把 c++ 引用的所有东东都解释清楚,然而我要指出的是 c++ 标准并没有解释编译器如何实现引用的行为。所以实现取决于编译器,而大多数情况下就是将其实现为一个指针常量

 

 

引用支持 c++ 机制的代码

 

#include 
class A{public: virtual void print() { cout<<"A.."<

上述代码使用引用支持虚函数机制。如果引用仅仅是一个别名,那如何实现虚函数机制,而虚函数机制所需要的动态信息只能通过指针才能实现,所以更加说明引用其实就是一个指针常量

好吧,我看过原文的评论之后,对这个结论又有了一些怀疑,因为下面的代码:

int a = 30;

int b = 40;
int &are = a;
printf("a:%d, are:%d", a, are);
are = b;
printf("b:%d, are:%d", a, are);

按照指针常量的定义:

指针常量是一个常量,在声明的时候一定要给它赋初始值。一旦赋值,以后这个常量再也不能指向别的地址。所以引用的定义还是参考原始的定义:

引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。

引用的声明方法:类型标识符 &引用名=目标变量名;

转载于:https://www.cnblogs.com/shenlanzifa/p/5288734.html

你可能感兴趣的文章
常用有三种json解析jackson、fastjson、gson。
查看>>
害死人不偿命的(3n+1)猜想-PTA
查看>>
Virtual Friends (HDU3172)
查看>>
利用IDE编写C语言程序的一点注意事项
查看>>
弹性光网络
查看>>
asp后台获取js中变量的值
查看>>
字符串和列表互相转换
查看>>
关于web界面设计的整体可维护性的感悟
查看>>
memcached配置
查看>>
java.lang.NoSuchMethodError: No static method getFont
查看>>
【求神——唐伯虎点秋香】
查看>>
Javascript Array和String的互转换
查看>>
GTD:让大脑用来思考,而不是用来记事!
查看>>
Spark程序进行单元测试-使用scala
查看>>
Oozie简单配置与使用
查看>>
根目录空间沾满
查看>>
python基础知识13-迭代器与生成器,导入模块
查看>>
Spring 操作Weblogic JDNI数据源
查看>>
bower程序包管理器与npm的对比及handlebars包的使用实例
查看>>
ES6 数值的扩展
查看>>