- 浏览: 34650 次
- 性别:
- 来自: 广州
最新评论
Introduction
I choose to write about references in C++ because I feel most of the people have misconceptions about references. I got this feeling because I took many C++ interviews and I seldom get correct answers about references in C++.
What is meant by references in C++? A reference is generally thought of as an aliasing of the variable it refers to. I hate the definition of references being an alias of a variable in C++. In this article, I will try to explain that there is nothing known as aliasing in C++.
Background
Both in C and in C++, there are only two ways by which a variable can be accessed, passed, or retrieved. The two ways are:
- Accessing/passing variable by value
- Accessing/Passing variable by address - In this case pointers will come into the picture
There is no 3rd way of accessing/passing variables. A reference variable is just another pointer variable which will take its own space in memory. The most important thing about the references is that it's a type of pointer which gets automatically dereferenced (by compiler). Hard to believe? Let's see....
A Sample C++ Code using References
Lets write a simple C++ code which will use references:
#include <iostream.h> 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 <<endl; // should print 11 11 // Now try to print the address of both variables i and j cout<< &i << &j <<endl; // surprisingly both print the same address and make us feel that they are // alias to the same memory location. // In example below we will see what is the reality return 0; }
References are nothing but constant pointers in C++. A statement int &i = j;
will be converted by the compiler to int *const i = &j;
i.e. References are nothing but constant pointers. They need initialization because constants must be initialized and since the pointer is constant, they can't point to anything else. Let's take the same example of references in C++ and this time we will use the syntax that the compiler uses when it sees references.
A Sample C++ Code using References (Compiler Generated Syntax)
#include <iostream.h> 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 <<endl; // should print 11 11 // A * is appended before j because it used to be reference variable // and it should get automatically dereferenced. return 0; }
You must be wondering why I skipped the printing of address from the above example. This needs some explanation. Since reference variables are automatically dereferenced, what will happen to a statement like cout << &j << endl;
. The compiler will convert the statement into cout << &*j << endl;
because the variable gets automatically dereferenced. Now &*
cancels each other. They become meaningless and cout
prints the value at j
which is nothing but the address of i
because of the statement int *const j = &i;
.
So the statement cout << &i << &j << endl;
becomes cout << &i << &*j << endl;
which is similar to printing the address of i
in both the cases. This is the reason behind the same address being displayed while we try to print normal variables as well as reference variables.
A Sample C++ Code using Reference Cascading
Here we will try to look at a complex scenario and see how references will work in cascading. Let's follow the code below:
#include <iostream.h> 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 <<endl; // increment variable j j++; // The print should be 11,11,11,11 cout<< i << "," << j << "," << k << "," << l <<endl; // increment variable k k++; // The print should be 12,12,12,12 cout<< i << "," << j << "," << k << "," << l <<endl; // increment variable l l++; // The print should be 13,13,13,13 cout<< i << "," << j << "," << k << "," << l <<endl; return 0; }
A sample C++ Code Using Reference Cascading (Compiler Generated Syntax)
Here we will see if we won't depend upon the compiler to generate constant pointers in place of reference and auto dereferencing the constant pointer, we can achieve the same results.
#include <iostream.h> 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 <<endl; // increment variable j (*j)++; // The print should be 11,11,11,11 cout<< i << "," << *j << "," << *k << "," << *l <<endl; // increment variable k (*k)++; // The print should be 12,12,12,12 cout<< i << "," << *j << "," << *k << "," << *l <<endl; // increment variable l (*l)++; // The print should be 13,13,13,13 cout << i << "," << *j << "," << *k << "," << *l <<endl; return 0; }
A Reference Takes its Own Space in Memory
We can see this by checking the size of the class which has only reference variables. The example below proofs that a C++ reference is not an alias and takes its own space into the memory.
#include <iostream.h> 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) <<endl; return 0; }
Conclusion
I hope that this article explains everything about C++ references. However I'd like to mention that C++ standard doesn't explain how reference behaviour should be implemented by the compiler. It's up to the compiler to decide, and most of the time it is implemented as a constant pointer.
Additional Notes to Support this Article
In the discussion forums for this article, people were having concerns that References are not constant pointers but aliases. I am writing one more example to support this fact. Look carefully at the example below:
#include <iostream.h> class A { public: virtual void print() { cout<<"A.."<<endl; } }; class B : public A { public: virtual void print() { cout<<"B.."<<endl; } }; class C : public B { public: virtual void print() { cout<<"C.."<<endl; } }; int main() { C c1; A &a1 = c1; a1.print(); // prints C A a2 = c1; a2.print(); // prints A return 0; }
The example using references supports the virtual mechanism, i.e. looking into the virtual pointer to get the handle to correct function pointer. The interesting thing here is how the virtual mechanism is supported by the static
type which is simply an alias. Virtual mechanism is supported by dynamic information which will come into the picture only when a pointer is involved. I hope this will clarify most of the doubts.
发表评论
-
句柄的本质
2013-03-22 10:25 658一、书上定义:<<Microsoft Windo ... -
聚簇索引与非聚簇索引的区别以及SQL Server查询优化技术
2013-03-12 17:04 610在《数据库原理》里面,对聚簇索引的解释是:聚簇索引的顺序就是 ... -
简洁、明晰!数据库设计三大范式应用实例剖析
2013-03-12 15:28 704引言 数据库的设计范式是数据库设计所需要满足的规范,满足这 ... -
关系数据库设计与范式
2013-03-12 15:20 1072今天先把关系数据库设计及范式相关知识回顾总结一下,大部分出自 ... -
扇区、磁道、柱面和簇的介绍
2013-03-12 11:51 1005一直以来对这几个概念 ... -
磁道、柱面、扇区、磁盘簇、寻道时间、旋转延迟、存取时间
2013-03-12 11:49 15391.磁道 以盘片中心为圆心,用不同的半径,划分出不同的很窄 ... -
关系模式规范化实例析解
2013-03-08 16:38 908关系模式规范化实例析解 2 ... -
气象站的故事-观察者模式
2013-03-08 15:41 717气象站的故事 现在我们要为一家气象站开发一套 ... -
关联、组合、聚合、依赖关系比较
2013-03-07 17:24 762类之间的关系 1. 种类: Generalization( ... -
用PV操作实现多线程间同步互斥(PV)
2013-03-06 22:16 6349在计算机操作系统中,PV操作是进程管理中的难点。 首先应弄 ... -
敏捷开发方法XP的12个最佳实践
2013-03-06 12:53 983极限编程(eXtreme Programming,简称XP) ... -
地址总线,字长,内存容量,寻址范围 之间的计算
2013-03-04 15:16 2584处理机字长是指处理机能同时处理(或运算)的位数,即同时处理多 ... -
输入输出控制
2013-02-21 17:05 618一般而言,CPU管理外围 ... -
原码,反码和补码
2013-02-21 16:35 584本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探 ... -
C++ 指针
2013-01-05 13:24 747Pointers We have already se ... -
回调函数
2013-01-05 13:18 684在计算机程序设计中, ...
相关推荐
source insight and windows via c++
insightface c++ 人脸关键点并进行对齐矫正 code for face alignment in c++
SourceInsight3.5 C/C++语言 源代码查看工具 破解版
人脸识别3:C/C++ InsightFace实现人脸识别Face Recognition(含源码):https://blog.csdn.net/guyuealian/article/details/130600571 人脸识别4:Android InsightFace实现人脸识别Face Recognition(含源码):...
C语言Java语言代码编辑器
Windows平台下的源代码阅读工具Source Insight 企业级源码查看和编辑工具,特别是在WINDOWS与Linux环境下的切换是相当方便的。国内外一线IT企业,嵌入式开发的王牌软件。 为了方便地学习Linux源程序,我们不妨...
在Source Insight中配置VISUAL C++ 2010编译运行环境,避免重装系统后重装Visual Studio。
SourceInsight工具,c++/c的强大开发工具,比vc好用多了
source insight 查看c++代码的工具软件,非常方便的查看继承关系,代码调用过程的非调试查看,定义和引用的跳转等等。
insight C/C++图形化调试器 insight C/C++图形化调试器
Source Insight has built-in dynamic analysis for C/C++, C#, Java, Objective-C, and more. Read More Powerful Editing Use powerful editing features, including code snippets, symbolic auto-completion, ...
SourceInsight静态C/C++代码扫描插件。 集成静态扫描在IDE中,帮助开发人员最快最低成本的发现潜在质量问题。 支持:规则配置,判空配置,误报屏蔽,快速跳转定位等功能。 功能清单 1.检测语法检查。 支持语法检查,...
View Changes 1. Macro event DocumentChanged was not called when a file...6. Search Results: Incorrect codepage might be used to display results for some searches using Lookup References and Search Files.
0. 此为C/C++的SourceInsight配置文件,其他语言的为默认。(字体颜色在其他编程语言有效) 1. 主要就是给那些习惯于等宽字体编程的人们。采用微软Vista自带的等宽字体:Consolas 2. 详情明细参考:...
source insight is the best code viewer. but it can't auto add ...the details how to add is saved in the file "how to add comment in source insight.txt". i tried it and it works. so, share it with you.
Principles and Practice Using C++"Addison-Wesley Professional | 2008 | ISBN: 0321543726 | 1272 pages | PDF | 129 MBAn Introduction to Programming by the Inventor of C++Preparation for Programming in ...
sourceinsight4.0 可用版本,外加sourceinsight3.x tabwnd标签控件
看过最好的sourceinsight主题,3.5试用,配色本人觉得非常舒服
New: Options > Load Configuration now has an option to import version 3.5 Custom Commands. Fix: C/C++ Source File: added *.hh file association Fix: Project > Add and Remove Project Files - fixed ...