C++对象使用指南:详解四种生存期和作用域

发表时间: 2018-08-01 18:09

一、四种对象生存期和作用域

栈对象

隐含调用构造函数(程序中没有显式调用)

堆对象

隐含调用构造函数(程序中没有显式调用),要显式释放

全局对象、静态全局对象

全局对象的构造先于main函数

已初始化的全局变量或静态全局对象存储于.data段中

未初始化的全局变量或静态全局对象存储于.bss段中

静态局部对象

已初始化的静态局部变量存储于.data段中

未初始化的静态局部变量存储于.bss段中

C++ Code

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

#include <iostream>

using namespace std;

class Test

{

public:

Test(int n) : n_(n)

{

cout << "Test " << n_ << " ..." << endl;

}

~Test()

{

cout << "~Test " << n_ << " ..." << endl;

}

private:

int n_;

};

int n; // 未初始化的全局变量,初始值为0。n存储于.bss段中。(block started by symbol)

int n2 = 100; // 已初始化的全局变量,初始值为100。n2存储于.data段中。

Test g(100); // 全局对象的构造先于main函数

static Test g2(200);

int main(void)

{

cout << "Entering main ..." << endl;

Test t(10); // 栈上创建的对象,在生存期结束的时候自动释放

{

Test t(20);

}

{

Test *t3 = new Test(30); // 堆上创建的对象,要显式释放

delete t3;

}

{

static int n3; // n3存储于.bss段中 (编译期初始化)

static int n4 = 100; // n4存储于.data段中 (编译期初始化)

static Test t4(333); // t4对象运行期初始化 .data段

}

cout << "Exiting main ..." << endl;

}

二、static 用法总结

1. 用于函数内部修饰变量,即函数内的静态变量。这种变量的生存期长于该函数,使得函数具有一定的“状态”。使用静态变量的函数一般是不可重入的,也不是线程安全的,比如strtok(3)。

2. 用在文件级别(函数体之外),修饰变量或函数,表示该变量或函数只在本文件可见,其他文件看不到也访问不到该变量或函数。专业的说法叫“具有internal linkage”(简言之:不暴露给别的translation unit)。

C语言的这两种用法很明确,一般也不容易混淆。

由于C++引入了类,在保持与C语言兼容的同时,static关键字又有了两种新用法:

3.用于修饰类的数据成员,即所谓“静态成员”。这种数据成员的生存期大于class的对象(实例/instance)。静态数据成员是每个class有一份,普通数据成员是每个instance 有一份。

4. 用于修饰class的成员函数,即所谓“静态成员函数”。这种成员函数只能访问静态成员和其他静态成员函数,不能访问非静态成员和非静态成员函数。