0
点赞
收藏
分享

微信扫一扫

由c++循环中局部变量地址不变而引发的思考


今天在用c++刷题的时候出现了一个bug,算法题所以免不了循环输入,而所有的代码自然也都嵌套在那个大循环中了。但是问题出现在:我在一个函数(不是main函数)的开头定义了一些局部变量(这个函数在程序中会被循环调用),但是既然是另外一个函数中定义的变量,我想着应该会在函数退出后自动释放了,那也就不需要每次循环都初始化一遍了。
然而事实上,如果不去给它初始化值的话,局部变量每次被声明后所在的地址是相同的,最可怕的是地址相同的话,里面的值就是上一次运行结束后的值。这也就意味着,c++在循环里面定义的变量的值在逻辑上是具有传递性的,当然可靠性不一定能保证。
下面直接放测试代码截图:
编译环境:codeblocks,语言:c++

第一张图:可以看出在​​make​​​函数中,如果不初始化​​i​​​,​​i​​​的值就是一个乱七八糟的数,但是初始化一次之后,即便以后不再初始化了,值也保留了下来。这很容易让人联想到​​i​​的地址一直是不变的,所以下面就测试了一下地址。

由c++循环中局部变量地址不变而引发的思考_初始化

第二张图:上面说到值可以“继承”下来,那么地址真的不变吗?从下图中看出,地址确实是不变的,每次调用该函数后产生的变量​​i​​的地址都相同。这就让人疑惑了,它是根据什么来分配地址的呢?是请求分配地址的时间吗?于是进行了第三个实验。

由c++循环中局部变量地址不变而引发的思考_地址分配_02

第三张图:这一次在​​make​​​函数中分情况定义了两个不同名称的局部变量,如果传进来的参数t为偶数,就定义变量​​i​​​,并输出​​i​​​的地址,如果传进来的参数​​t​​​为奇数,就定义变量​​j​​​,然后输出它的地址。神奇的一幕发生了,​​i​​​的地址全都是相同的,​​j​​​的地址也都是相同的,但是​​i​​​和​​j​​​的地址是不同的。从第一次申请空间的时间来看,​​j​​​在​​i​​​之后,因此根据​​c++​​​局部变量控件分配到栈里,是从大到小的顺序,​​j​​​的地址比​​i​​​小4是没错的。但是第一次循环中​​i​​​的地址如果被释放,第二次进来申请​​j​​​的地址应该和第一次​​i​​的地址是相同的,然而事实并没有。而编译器如果确实是按照顺序分配空间的话,第一次的i的空间有可能根本就没有被真正的释放,只是以某种外界不可访问的方式存在。

由c++循环中局部变量地址不变而引发的思考_局部变量地址_03

论坛里看到有人说​​栈上的内存是顺序分配的, pop出来,再push进去。还是在原来的位置​​​,这种说法应该是错误的,不然图三中​​j​​​的地址应该和​​i​​的地址相同。

但是具体的原因仍旧不得而知了,希望以后能搞清楚这个问题。但是在刷题中要注意的是,在循环中,即便局部变量的申明也必须初始化!!!


举报

相关推荐

0 条评论