探讨C++ 变量生命周期、栈分配方式、类内存布局、Debug和Release程序的区别(一)

今天看博客园的文章,发现博问栏目中有一个网友的问题挺有趣的,就点进去看了下,标题是“C++生存期问题”,给出链接:http://q.cnblogs.com/q/51133/

本文会以此问题作为讨论的实例,来具体讨论以下四个问题:

(1) C++变量生命周期

(2) C++变量在栈中分配方式

(3) C++类的内存布局

(4) Debug和Release程序的区别

也许您觉得这些讨论问题没有实际意义,应该多做些提高生产力的事情,如同重复发明轮子也是没有意义的。

笔者同意这个观点,但是,作为一个有追求的程序员,应该知其然而且知其所以然,更应该知道轮子是怎么造出来的,不是吗?

当然,限于篇幅,本文可能只是抛砖引玉,更多的知识,一定是大家自己去探索的。

不多说,进入正题。

实验环境:Win7 32bit系统 + VS2008 SP1

问题现象:

先阅读以下程序:

#include "stdafx.h"
#include<iostream>
#include<windows.h>
using namespace std;
class T
{
protected:
    int t;
public:
    T(int r=0):t(r){}
    void showNum(){cout<<t<<endl;}
};

class T1:public T
{
private:
   int x;
public:
    T1(int r):x(r),T(r){}
    void show(){cout<<"x="<<x<<endl;}
};

class T2:public T
{
private:
    int x;
public:
    T2(int r):x(r*r),T(r){}
    void show(){cout<<"x="<<x<<endl;}
};

void main()
{
    T* p[10];
    for(int i=0;i<5;i++)
    {
        if(i%2==0)
        {
            T1 r(2);
            p[i]=&r;
            cout<<&r<<endl;
        }
        else
        {
            T2 r(3);
            p[i]=&r;
            cout<<&r<<endl;
        }
    }
    for(int i=5;i<10;i++)
    {
        if(i%2==0)
        {
            T1 r(4);
            p[i]=&r;
            cout<<&r<<endl;
        }
        else
        {
            T2 r(5);
            p[i]=&r;
            cout<<&r<<endl;
        }
    }
    for(int i=0;i<10;i++)
    {
        p[i]->showNum();
    }
    system("pause");
}

不急着往下看,先预测此程序输出。

一般来说,我们预测的输出会是什么结果呢?

首先Debug版本和Release版本应该输出结果是相同的,或者规律是相同的。

当0 <= i < 5时,输出5个地址,应该是不同的,逐个递增,生成的局部变量存放在栈中;

当5 <= i < 10时,又输出5个地址,应该也是不同的,也是逐个递增,生成的局部变量存放在栈中;

最后循环调用p[i]->showNum()这个方法10次,输出的结果应该是不可知的,因为P[i]指向的对象都已经失效。

我们来看看实际输出的结果:

Debug版本:

探讨C++ 变量生命周期、栈分配方式、类内存布局、Debug和Release程序的区别(一)

当0 <= i < 5时,输出5个地址,是一种交替状输出,分别是001FF750和001FF740。

当5 <= i < 10时,又输出5个地址,也是交替状输出,分别是001FF714和001FF724。

最后循环调用p[i]->showNum()这个方法10次,输出的结果是正确的,似乎那些栈中的局部对象未失效。

Release版本:

探讨C++ 变量生命周期、栈分配方式、类内存布局、Debug和Release程序的区别(一)

当0 <= i < 5时,输出5个地址,是一种交替状输出,分别是001CFB00和001CFB08。

当5 <= i < 10时,又输出5个地址,也是交替状输出,奇怪的是地址的值也是001CFB00和001CFB08。

最后循环调用p[i]->showNum()这个方法10次,输出的结果全是5和4,似乎前5次输出失效了,后5次没有失效。

为什么?

大家可以先思考,有想法可以留言指出。限于篇幅,笔者的下一篇博客将给出具体的分析。

相关分析的博文已经写好:探讨C++ 变量生命周期、栈分配方式、类内存布局、Debug和Release程序的区别(二)

原文链接: https://www.cnblogs.com/yylwuwei/p/3146306.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/92742

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月10日 上午1:50
下一篇 2023年2月10日 上午1:50

相关推荐