Geekband C++学习笔记——浅谈引用与指针
来源:互联网 发布:网络巫师剧情介绍 编辑:程序博客网 时间:2024/05/16 18:33
扯淡
在博文开始之前,先扯个淡,灌灌水。作为一个研究嵌入式的学生来说,最为熟练的是C语言,因此对于指针还是很有心得的。前几天的直播李建忠老师讲述了C语言之父描述C语言是充分信任程序员的理念,我对这个理念还是很有心得的,理解计算机组成原理与体系结构对程序员编写程序其实是很有意义的。而直接操作硬件底层、操作内存,也是很有趣的。
引用与指针分析
回到正题,不论是上课还是直播时,侯捷老师和李建忠老师都说了,其实引用的底层就是指针。那么,怎么理解这码事情呢?先写段小test,看看结果吧。
//test.cint main(){ int a[3] = {1, 2, 3}; int& b = a[0]; int *c = a;}
为了看到底层,我们对其进行用编译器对其汇编,产生汇编码,g++ -S test.c -o test.s,结果如图:
红色圈起来的就是上述代码的汇编码,要注意的是,我采用的编译器是gcc,汇编码是AT&T汇编,和INTEL汇编的习惯还是有些不同的。我们根据这段汇编码可以画一个内存模型出来:
可以看到,不管是引用变量还是指针变量,它们最终在内存空间中都存放的是地址。根据之前的汇编码,在内存地址(%rbp-32)处是引用底层所存储的地址,而(%rbp-24)则是指针对应的地址。我们都很清楚,引用是变量的别名,不论对引用取地址还是直接取引用的值都是所引用变量的地址和值,那么如何通过C++看到引用变量本身的地址以及该内存中存的内容呢,也就是上图所示的内存空间呢。我们可以根据上图内存布局来编个代码,解决这个问题:
#include <iostream>using namespace std;int main(){ int a[3] = {1, 2, 3}; int& b = a[0]; int *c = a; unsigned long long *d = (unsigned long long *)&a[-4] //笔者的机器是64位的,引用所在的内存地址为a[-4]的地址,且还需要进行类型转换,因为该地址处存放的是a[0]的地址,是一个64位的无符号数,也就是上图的%rbp-16 cout << a << endl; //a[0]的地址 cout << &b << endl; //对引用取地址 cout << b << endl; //取引用的值 cout << &c << endl; //指针c自身的地址 cout << c << endl; //指针c cout << d << endl; //引用变量"本身"底层的地址 cout << "0x" << hex << *d << endl; //引用变量"本身"在底层的内存地址处存储的内容}
编译,运行结果如下:
从结果可以看到为指针和引用所开辟的空间所在内存地址分别为0x7fff4d73c6f8与0x7fff4d73c700,两者相差8,与内存布局图中的(%rbp-24)与(%rbp-32)一致,同时,这两处内存中存放的内容都为0x7fff4d73c710,即a[0]的地址,很容易就说明了引用与指针在底层都是地址。
结束语
既然引用与指针在底层都是一样的,那为什么两者的操作完全不同呢,甚至对引用&取地址取到的都是所引用的变量的地址。其实,根据上一节的分析,就可以看出引用其实是做了封装的,屏蔽掉了指针麻烦的地方。根据上一节的分析,我们可以自己实现一个简单的引用类,虽然没有c++本身的功能强大,但是,也算是一个总结了:
#include <iostream>using namespace std;/* run this program using the console pauser or add your own getch, system("pause") or input loop */template<typename T>class Refer{public:Refer(T& r){pt = new T*;*pt= &r;}inline unsigned long long* operator&(){return (unsigned long long *)(*pt);} inline Refer<T> operator=(Refer<T>& r){if(this->pt == r.pt){return *this;}delete pt;pt = new T*;*pt = &r;return *this;}inline Refer<T> operator=(T& r){delete pt;pt = new T*;*pt = &r;return *this;}friend inline ostream& operator<< (ostream &os, const Refer<T>& r){return os << *(*r.pt);}friend inline ostream& operator<< (ostream &os, const Refer<T> *r){return os << hex << (unsigned long long *)(*r->pt);}private:T **pt;};int main(int argc, char** argv) {int a = 10;Refer<int> b(a);Refer<int> c = a;Refer<int> d = c;cout << &a << endl;cout << a << endl;cout << &b << endl;cout << b << endl;cout << &c << endl;cout << c << endl;cout << &d << endl;cout << d << endl;return 0;}
在dev-c++编译运行结果如图:
很显然,达到了引用的部分效果,不过呢,远远还不够吧,哈哈,也算是辛苦了值得庆祝一下。要是有什么地方有不当之处,也请多多指点。
- Geekband C++学习笔记——浅谈引用与指针
- C++学习笔记:C的继承与超越——指针与引用
- GeekBand C++学习笔记——迭代器
- C++primer学习笔记——引用和指针
- C/C++学习笔记11:指针与引用的区别
- 《More Effective C++》学习笔记之一引用与指针
- C与指针学习笔记——函数指针
- C与指针学习笔记——有效的指针
- GeekBand C++学习笔记——继承、复合当中的构造与析构
- GeekBand C++学习笔记——内存模型与类大小的计算
- GeekBand c++学习笔记——C++中的内存天下(2),new与delete拾遗
- 学习笔记—面向对象高级篇上(GeekBand)
- C++学习——引用与指针
- 浅谈C++引用与指针
- C++学习笔记->指针与引用
- GeekBand C++学习笔记
- 《C与指针》学习笔记
- 《C与指针》学习笔记
- JAVA三大特性复习总结(学习笔记)
- Linux学习笔记:vim的初步使用
- String字符串与整数之间的相互转换
- Hihocoder 1039 : 字符消除
- 面试相关知识点(一)
- Geekband C++学习笔记——浅谈引用与指针
- 【BZOJ3622】已经没有什么好害怕的了,两次DP
- Cube 逐点运动到点停止
- c++头文件问题
- android 无法连接真机调试
- 算法代码实现之堆排序,Java实现
- hadoop 集群调度 Azkaban2搭建
- Uva10305——Ordering Tasks
- 使用 iframe 实现在同一页面中显示不同的内容