谁改了我的const引用?
2016-03-09 22:42
225 查看
注:转载必须注明出处,绝对原创
曾经在工作中遇到一个问题:
两个指针指向同一块堆地址,如果一个指针释放了,那么另一个指针怎么知道呢?
1:在debug中,可以通过指针释放之后那段内存的值是多少可以初步推断,一般有0xcccccccc,
或者0x000000,或者0xffffff。但是这个根据编译器不同而不同,一般程序的发布版本都会用release
版本。
2:在release中,释放的堆内存有优化,值是个随机的数,那就没办法判断了。
最开始我想到了引用,我想既然有指针变量的引用,那么是不是一个指针释放了,那么就可以
通过引用知道呢?(如果你对引用了解的足够本质,你绝不会有这种想法)
以前我写过一个程序:
程序如下:
两次同样的连续的,对同一个变量的输出语句,竟然结果不一样!细心的同学会发现,
用vs或者g++在编译的时候会有一个警告:warning C4172: returning address of local variable or
temporary
或者:warning: reference to local variable 'p' returned
没错,我们fun函数返回的变量是个局部变量,不要认为没什么关系
1:首先,有警告就是编程不规范,除非你知道你做的绝对没错,可是这里,你保证不了
2:不要认为“可是我的堆没释放,返回也可以接着用啊”,那么你怎么解释两次的输出结果
不一样呢?
这也就涉及到引用的本质是什么了,最开始学引用,看书本的介绍,总感觉引用特别神奇,
以为编译器做了什么神奇的操作(使引用不成为一个对象,不占内存空间,只是别人的一
个别名,神一般的感觉!),通过自己写程序,看汇编,才发现,原来他的实现方式就是
指针,其实他占内存,除了使用方法有点不同,就是一个常量指针的功能(一对一),
引用的本质更像指针(一对多)的一个子集。
引用多一个&可以说就是代表多一级指针,只是使用方式按照没有&的方式使用,
编译器做了(*解引用操作)。上面的程序,可以很方便的改成二级指针。结果类似。
其实是编程不规范和对引用的本质了解的不够的原因,你可以把fun里面的p改成static,
就好了
那么,输出结果不一样的原因是什么:看下图
引用了(二级指针指向了)一个局部变量(在栈中),那么,回到fun调用完之后,主函数的
cout也会有入栈,这样其实你们看看汇编代码就知道,栈中的那个引用值被cout的入栈覆盖了。
类似的,改成二级指针供参考
曾经在工作中遇到一个问题:
两个指针指向同一块堆地址,如果一个指针释放了,那么另一个指针怎么知道呢?
1:在debug中,可以通过指针释放之后那段内存的值是多少可以初步推断,一般有0xcccccccc,
或者0x000000,或者0xffffff。但是这个根据编译器不同而不同,一般程序的发布版本都会用release
版本。
2:在release中,释放的堆内存有优化,值是个随机的数,那就没办法判断了。
最开始我想到了引用,我想既然有指针变量的引用,那么是不是一个指针释放了,那么就可以
通过引用知道呢?(如果你对引用了解的足够本质,你绝不会有这种想法)
以前我写过一个程序:
程序如下:
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int *& fun() { const int *p=new int[100]; return p; } int main() { const int *const &p1 = fun(); cout<<"before p1 :"<<hex<<p1<<endl; cout<<"after p1 :"<<hex<<p1<<endl; getchar(); return 0; } 结果如下:before p1 :003D5218 after p1 :10572AC8
两次同样的连续的,对同一个变量的输出语句,竟然结果不一样!细心的同学会发现,
用vs或者g++在编译的时候会有一个警告:warning C4172: returning address of local variable or
temporary
或者:warning: reference to local variable 'p' returned
没错,我们fun函数返回的变量是个局部变量,不要认为没什么关系
1:首先,有警告就是编程不规范,除非你知道你做的绝对没错,可是这里,你保证不了
2:不要认为“可是我的堆没释放,返回也可以接着用啊”,那么你怎么解释两次的输出结果
不一样呢?
这也就涉及到引用的本质是什么了,最开始学引用,看书本的介绍,总感觉引用特别神奇,
以为编译器做了什么神奇的操作(使引用不成为一个对象,不占内存空间,只是别人的一
个别名,神一般的感觉!),通过自己写程序,看汇编,才发现,原来他的实现方式就是
指针,其实他占内存,除了使用方法有点不同,就是一个常量指针的功能(一对一),
引用的本质更像指针(一对多)的一个子集。
引用多一个&可以说就是代表多一级指针,只是使用方式按照没有&的方式使用,
编译器做了(*解引用操作)。上面的程序,可以很方便的改成二级指针。结果类似。
其实是编程不规范和对引用的本质了解的不够的原因,你可以把fun里面的p改成static,
就好了
那么,输出结果不一样的原因是什么:看下图
引用了(二级指针指向了)一个局部变量(在栈中),那么,回到fun调用完之后,主函数的
cout也会有入栈,这样其实你们看看汇编代码就知道,栈中的那个引用值被cout的入栈覆盖了。
类似的,改成二级指针供参考
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int ** fun() { const int *p=new int[100]; return &p; } int main() { const int **const p1 = fun(); cout<<"before p1 :"<<hex<<*p1<<endl; cout<<"after p1 :"<<hex<<*p1<<endl; getchar(); return 0; }结果为:before p1 :002A5218 after p1 :10572AC8 那么回到题目,你就知道,所谓的常量指针,所谓的(常量)对const引用,都不过是‘不能通过他们自己改变值’罢了,其他人是可以改他们‘自认为’的常量的。
相关文章推荐
- 第2周项目2就拿胖子说事
- mac tips
- 请用rand1To5实现等概率随机产生1~7的随机函数rand1To7
- 问题
- 2016-03-09c中指针与数组学习记录
- 奥特曼 剧情
- IOS学习之performSelector:withObject:afterDelay:
- 2.5.3全局变量与局部变量
- 1.2 数据抽象(Part 1 -- Exercises)
- SQL 优化经验总结34条(转)
- 关于git,你需要知道一点命令
- Socket网络编程总结
- 搭建linux服务器之Debian安装
- [Leetcode]Jump Game II
- num的power次方
- MapReduce剖析笔记之二:Job提交的过程
- Python使用线程来接收串口数据
- linux之split命令
- How to Install Oracle Java JDK on Ubuntu Linux
- 双色球