C++中的生存期和作用域

原创 2006年05月27日 09:18:00

生存期和作用域,究竟有什么样的关系呢?

先解释一下生存期吧。
一个进程对应的内存空间中,包含5种不同的数据区。
按照内存中从低到高的顺序,分别为:栈、堆、BSS段、数据段和代码段。
栈:存放程序临时创建的局部对象。一般VC++6.0生成的可执行文件只有1MiB多的栈。
堆:存放进程运行中被动态分配的内存段。它大小并不固定,可动态扩张或缩减。属于内存中最多的资源。
BSS段:(它是block started by symbol的缩写)存放程序中未初始化全局对象,操作系统将自动把BSS段全部置零。
数据段:存放已初始化的全局对象和静态对象。
代码段:存放可执行文件的操作指令,即可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以是只读的。
可以看出,只有代码段是被操作系统保护为只读的,其他地方的常量都只被编译器保护。
当然,内存中还有很多不属于数据区的,它们是不可读写的。
在栈中的数据,生存期为包含它的{};
在堆中的数据,生存期为它被free或delete释放前。
其他的数据,生存期为进程结束前。
用户定义的变量或常量,在生存期内,除非用户自行更改或被外界因素更改,否则不会被更改。

作用域则是可以直接显式使用该变量或常量的区域。
注:这只是我自己下的定义,这样堆中的数据应该是没有作用域的,因为它不能被直接显示使用(需要通过指针或引用)。
除了局部静态变量的作用域为为包含它的{}以外,其他和生存期相同。

下面做个简单的测试,写得很乱,看不下去的看结论就行了。

 


 

// File Name : life_test.cpp
// Author : keakon
// Create Date : 2006/5/26
// Last Edited Date : 2006/5/27
// 测试各种对象的生存期和作用域
// 在VC++6.0下编译运行通过
/////////////////////////////////////////
#include <iostream>
#include <string>

using std::cout;
using std::string;
/////////////////////////////////////////
class A
{
public:
 A(string const& name) : m_Name(name) {cout << m_Name << ".A::A()/n";}
 ~A() {cout << m_Name << ".A::~A()/n";}
 string const& getName() const {return m_Name;}
private:
 string m_Name;
};
/////////////////////////////////////////
A g("g");
const A g_c("g_c");
static A g_s("g_s");
const static A g_c_s("g_c_s");

const int NUM = 10; //存放指针数组的大小
/////////////////////////////////////////
void print(A const* p[])
{
 cout << "/n/n";
 for (int i = 0; i < NUM; ++i)
 {
  cout << p[i]->getName() << " :/t" << p[i] << '/n';
 }
 cout << "/n/n";
}
/////////////////////////////////////////
void printName(A const* p[])
{
 cout << "/n/n";
 for (int i = 0; i < NUM; ++i)
 {
#ifndef NDEBUG
//如果没有定义NDEBUG,跳过4、5、8和9,因为对象已被析构
//NDEBUG是VC++6.0的一个系统宏,在debug模式下未定义,在release模式下被定义
//可以看见release模式下,4、5、8和9号对象的name变成乱码
//若取消该宏,在debug模式下会出错
//这和2种模式对离开了生存期的变量的处理方式不同有关
//PS:若取消该宏,g++下可能会打出几屏幕乱码^^
  if (i == 4 || i == 5 || i == 8 || i == 9)
  {
   continue; //进入下一次for循环
  }
#endif
  cout << p[i]->getName() << " :/t" << p[i] << '/n';
 }
 cout << "/n/n";
}
/////////////////////////////////////////
void assign(A const* p[])
{
 A l("l");
 const A l_c("l_c");
 static A l_s("l_s");
 const static A l_c_s("l_c_s");
 register A r("r");

 p[0] = &g;
 p[1] = &g_c;
 p[2] = &g_s;
 p[3] = &g_c_s;
 p[4] = &l;
 p[5] = &l_c;
 p[6] = &l_s;
 p[7] = &l_c_s;
 p[8] = new A("l_h"); //不检查是否失败了,留给自己的人品去检验吧
 p[9] = &r;

 print(p);

 delete p[8];
}
/////////////////////////////////////////
namespace test
{
 const string str("keakon是帅哥=。=");

 const string& getStr()
 {
  return str;
 }

 void printStr()
 {
  cout << str << "/n/n/n";
 }
}
/////////////////////////////////////////
int main()
{
 A const* p[NUM] = {NULL}; //全赋值为NULL

 assign(p);
 printName(p);

 assign(p);
 printName(p);

 string const &pi = test::getStr(); //其实也可以用指针的,不过感觉引用更直观
 const_cast<string&>(pi) = "keakon是美女^^v"; //更改了常量,汗=。=
 test::printStr(); //输出“keakon是美女^^v”

 return 0;
}

/*
注:
1.命名时,g表全局,l表局部,c表常量,s表静态,h表堆,r表寄存器
2.下述结论使用“对象”来表示可以是变量,也可以是常量;因为我想不到有什么好词来表示
3.以下结论仅在VC++6.0中有效

结论:
1.全局对象有static属性(地址和static对象放在一起)
2.寄存器对象有auto属性(地址和auto对象放在一起)//忘记在哪本书上看见的,貌似不能对register对象取地址
3.局部非静态对象(包括常量对象、寄存器对象和堆对象)在脱离作用域后,对象的内容是随机的
4.静态对象在脱离作用域后(程序结束前),仍可以被正常访问,且内容保持不变
5.处于另一个namespace的对象也符合上述结论(这里只测试了全局对象)
6.全局或静态对象析构时,编译器可能已将其他非静态对象析构了(如cout),因此可能不会输出信息。
实际上,如果全局或静态对象有非静态的成员的话,在它析构前,它的这些成员就已经被析构了。
*/

相关文章推荐

C++ 标识符作用域以及对象生存期

1、C++中标识符作用域: 函数原型作用域:在函数声明中形参列表左右括号之间; 局部作用域(块作用域):声明变量所在的大括号之间 类作用域:类的成员所具有的作用域 命名空间作用域:using ...

从零开始学C++之对象的使用(二):四种对象生存期和作用域、static 用法总结

一、四种对象生存期和作用域 栈对象 隐含调用构造函数(程序中没有显式调用) 堆对象 隐含调用构造函数(程序中没有显式调用),要显式释放 全局对象、静态全局对象 全局对象的构造先于m...

十三、对象的使用(二)四种对象的作用域与生存期、static用法总结、static与单例模式

一、四种对象的作用域与生存期 栈对象:隐含调用构造函数(程序中没有显示调用)堆对象:隐含调用构造函数(程序中没有显示调用)全局对象、静态全局对象:全局对象的构造先于main函数 已初始化...
  • tianttt
  • tianttt
  • 2015年01月04日 20:52
  • 493

C语言中变量的生存期及作用域介绍

c 语言中变量的初始化及生存期、作用域浅谈生存期和作用域相关的关键字extern,static,auto,register 变量的初始化相关问题关键字介绍 extern extern 可以作用于变...

嵌入式学习10(C语言五大内存区间,变量的作用域和生存期,变量的存储类型)

今天又是元气满满的一天 C语言的五大内存区间 1、  栈区(stack):函数的形参和局部变量,先入后出,由编译器自动分配,自动释放 2、  堆区(heap):一般由程序员分配释放,若程序员不释...

关于C变量作用域和生存期的常见问题

作用域 作用域描述了程序中可以访问一个标识符的一个或多个区域,一个C变量的作用域可以是代码块作用域、函数原型作用域,或者文件作用域。代码块是包含在一对花括号内的一 段代码,在代码块中定义的变量具有代码...
  • xgf415
  • xgf415
  • 2016年07月21日 19:12
  • 1641

Lisp的作用域和生存期(scope and extent in lisp)

在lisp语言中,scope和extent的概念非常常见。作用域和生存期说的是对象或者是结构在程序的什么时候被引用。作用域指的是空间或者文本域。生存期指的是引用的时间间隔。这两个概念是紧密联系的概念。...

C语言的变量的作用域和生存期

C语言的变量的作用域和生存期                摘自http://blog.csdn.net/piaojun_pj/article/details/5890186   一、c程序...

08.作用域和生存期

变量的作用域(scope):变量起作用或有效的代码范围,空间。 变量的生存期(life time):变量存在的时间范围,时间。根据变量的作用域将变量分为全局变量和局部变量 全局变量储存在静态数据区...

C++参数传递与作用域

  • 2011年07月18日 14:37
  • 1005KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++中的生存期和作用域
举报原因:
原因补充:

(最多只允许输入30个字)