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++编译运行结果如图:



很显然,达到了引用的部分效果,不过呢,远远还不够吧,哈哈,也算是辛苦了值得庆祝一下。要是有什么地方有不当之处,也请多多指点。

1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 驾校不给补科一成绩单怎么办 外地驾照转广州体检表怎么办 驾照体检表签名签错怎么办 改完名字后护照怎么办 办健康证没有身份证怎么办 身份证掉了怎么办健康证 华师附小不搬了怎么办 健康证快到期了怎么办 老公想去日本打工怎么办 学生没有资产证明怎么办日本签证 在读证明学校不按模版怎么办 办日本签证没有户口本怎么办 日本大学留级续签失败怎么办 法国签证递交时间太晚怎么办 日本留学生签证更新拒签怎么办 永驻拒签了我该怎么办 越南签证拒签了怎么办 l1签证续签被拒怎么办 去日本跟团签证怎么办 手表里指针掉了怎么办 北京居住证过期半年了怎么办 居住证明居委会不盖章怎么办 小孩感冒鼻子不通气怎么办 1岁宝宝喉咙痰多怎么办 两个月喉咙有痰怎么办 10个月咳嗽有痰怎么办 昆山初级会计审核没有居住证怎么办 初级会计审核没有居住证怎么办 哈尔滨原房主户口不牵走怎么办 在亲戚家住怎么办居住证 按揭车押金不退怎么办 护照到期韩国签证没到期怎么办 日本签证银行流水不够怎么办 想去日本cm签证怎么办 护照在签让那里怎么办 泰国出境单丢了怎么办 居住证到期了忘记续签了怎么办 贵州交警app忘记密码怎么办 科一第一次没过怎么办 社保转移时学历信息不符怎么办 天津摇号密码忘了怎么办