您的位置:首页 > 其它

谁改了我的const引用?

2016-03-09 22:42 225 查看
注:转载必须注明出处,绝对原创

曾经在工作中遇到一个问题:

两个指针指向同一块堆地址,如果一个指针释放了,那么另一个指针怎么知道呢?

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引用,都不过是‘不能通过他们自己改变值’罢了,其他人是可以改他们‘自认为’的常量的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: