探讨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版本:

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

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

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

Release版本:

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

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

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

为什么?

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

 
 
分类: 编程语言

探讨C++ 变量生命周期、栈分配方式、类内存布局、Debug和Release程序的区别的更多相关文章

  1. java 静态变量生命周期(类生命周期)

    Static: 加载:java虚拟机在加载类的过程中为静态变量分配内存. 类变量:static变量在内存中只有一个,存放在方法区,属于类变量,被所有实例所共享 销毁:类被卸载时,静态变量被销毁,并释放 ...

  2. java 静态变量生命周期(类生命周期)(转)

    Static: 加载:java虚拟机在加载类的过程中为静态变量分配内存. 类变量:static变量在内存中只有一个,存放在方法区,属于类变量,被所有实例所共享 销毁:类被卸载时,静态变量被销毁,并释放 ...

  3. Android开发工程师文集-Activity生命周期,启动方式,Intent相关介绍,Activity详细讲解

    前言 大家好,给大家带来Android开发工程师文集-Activity生命周期,启动方式,Intent相关介绍,Activity详细讲解的概述,希望你们喜欢 Activity是什么 作为一个Activ ...

  4. react篇章-React State(状态)-将生命周期方法添加到类中

    将生命周期方法添加到类中 在具有许多组件的应用程序中,在销毁时释放组件所占用的资源非常重要. 每当 Clock 组件第一次加载到 DOM 中的时候,我们都想生成定时器,这在 React 中被称为挂载. ...

  5. Activity具体解释(生命周期、启动方式、状态保存,全然退出等)

    一.什么是Activity? 简单的说:Activity就是布满整个窗体或者悬浮于其它窗体上的交互界面. 在一个应用程序中通常由多个Activity构成,都会在Manifest.xml中指定一个主的A ...

  6. C语言 遍历流程 变量生命周期

    来自c程序设计 谭浩强 程序编译流程 运行c程序的步骤 在编好一个c程序后.怎样上机进行编译运行呢?一般要经过一下几个步骤: 上机输入和编辑源程序.通过键盘和计算机输入程序,如果发现有错误,要及时改正 ...

  7. 面向过程—面向对象(C++的封装,this)_内存四区_变量生命周期

    1.面向对象主要涉及  构造函数.析构函数.虚函数.继承.多态等. 2.对各种支持 的底层实现机制 c语言中,数据 和 处理数据的操作(函数) 是分开来声明,即语言本身并没有支持 “数据和函数”的关联 ...

  8. 线程:生命周期、实现方式、start()和run()的区别!

    1.线程的生命周期 要想实现多线程,必须在主线程中创建新的线程对象.Java语言使用Thread类及其子类的对象来表示线程,在它的 一个完整的生命周期中通常要经历如下的五种状态: 新建:当一个Thre ...

  9. 2.Spring的Bean生命周期和组装方式

    1.Spring IoC容器概述 Spring IoC容器: Spring容器即体现了IoC原理    Spring容器通过读取配置元数据负责对Beans实例化.配置和装配     配置元数据可以用X ...

随机推荐

  1. 在 CentOS 上安装 Tomcat7

    1. 下载 #可以直接在官网下载然后传到服务器上,也可以直接下载#下载地址:http://tomcat.apache.org/download-70.cgi 2. 安装 # tar -xzvf apa ...

  2. Windows下用C语言连接Mysql注意问题

    原文:Windows下用C语言连接Mysql注意问题 环境是:在VS6.0 安装Mysql后,我们需要相应的头文件以及lib文件,所以安装过程必须是完整安装.否则不会生成include文件夹哦~ 具体 ...

  3. MySQL在Windows和Linux减少数据库

    Linux减少数据库代码: 1,创建一个空数据库cddl mysql> create database cddl; Query OK, 1 row affected (0.00 sec) 2,还 ...

  4. Android使用OpenGL ES2.0显示YUV,您的手机上的数据要解决两个方面的坐标

    如果说 ,我不知道,如果你不明白这个话题.连接到:http://blog.csdn.net/wangchenggggdn/article/details/8896453(下称链接①), 里面评论有非常 ...

  5. Linux下防火墙设置

    Linux下开启/关闭防火墙命令  1) 永久性生效,重启后不会复原 开启:chkconfigiptables on 关闭:chkconfigiptables off 2) 即时生效,重启后复原 开启 ...

  6. Katana介绍以及使用

    Katana介绍以及使用 接上篇OWIN产生的背景以及简单介绍,在了解了OWIN规范的来龙去脉后,接下来看一下Katana这个OWIN规范的实现,并看看如何使用在我们的Web开发中. 阅读目录: 一. ...

  7. Oracle中join left,join right,inner join,(+) 等

    Oracle中join left,join right,inner join,(+) 等 博客分类: Oracle   建表create table TEST1create table TEST1(  ...

  8. php中session和cookie

    cookie 每次请求页面的时候进行验证,如果用户信息存储在数据库中,每次都要执行一次数据库查询,给数据库造成多余的负担.cookie可以被修改的,所以安全系数太低. session是存储在服务器端面 ...

  9. Mock原理学习

    同事搓蛋问了我一个问题,mock的原理是啥,没怎么想出来,于是花了点时间学习了一下. 从Moq这个库入手:https://github.com/moq/moq4 Moq用到了Castle的库用于Dyn ...

  10. [翻译]用Dart塑造Android未来

    明天回家,今天下午瞅时间翻译了Cyril Mottier的另外一篇有关Android前景的文章. 原谅地址是:http://cyrilmottier.com/2014/06/12/shaping-th ...