Chinaunix首页 | 论坛 | 博客
  • 博客访问: 285845
  • 博文数量: 111
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 816
  • 用 户 组: 普通用户
  • 注册时间: 2014-05-04 20:35
文章分类

全部博文(111)

文章存档

2016年(1)

2015年(5)

2014年(105)

我的朋友

分类: C/C++

2014-06-10 21:56:05

引用地址:http://blog.sina.com.cn/s/blog_704c28fc0100lnvc.html

个人看法:说明在初始化对象时,对有递归定义的类型,是有特殊处理机制的。

故事从这个问题开始:如果一个类的析构函数是private的那么能不能在栈上实例化该类?

刚开始动手去试可能会像下面去实例化f1, f2,f3,b2,b3. 结果发现都是无法通过编译。可是有人却想出来b1这样实例化的方法。

#include"stdafx.h"

#include

usingnamespace std;

class Foo

{

~Foo()

{

cout<<"Foo destructor."<

}

};

class Bar

{

~Bar()

{

cout<<"Bar destructor."<

}

static Bar b1;

//static Foo f1; //compile error: cannot access private member declared in class 'Foo'

//Foo f2;

};

Bar Bar::b1;

//static Bar b2;

//Foo Bar::f1;

//Foo f3;

int _tmain(int argc, _TCHAR* argv[])

{

//Bar b3; //compile error: cannot access private member declared in class 'Bar'

return 0;

}

为什么f1,b2不行,b1却可以呢?在Bar Bar::b1;处设断点进行debug,发现该处assembly中有这样一句:0041614E push offset `dynamic atexit destructor for 'Bar::b1'' (417180h)

Call Stack:

Name

Lang

TestCpp.exe!`dynamic initializer for 'Bar::b1''() Line 27 + 0x1 bytes

C++

msvcr80d.dll!_initterm(void (void)* * pfbegin=0x00419208, void (void)* * pfend=0x0041930c) Line 855

C

TestCpp.exe!__tmainCRTStartup() Line 512 + 0xf bytes

C

TestCpp.exe!wmainCRTStartup() Line 414

C

查阅msdn

int atexit(

void (__cdecl *func )( void )

);

The atexit function is passed the address of a function (func) to be called when the program terminates normally. Successive calls to atexit create a register of functions that are executed in last-in, first-out (LIFO) order. The functions passed to atexit cannot take parameters. atexit and _onexit use the heap to hold the register of functions. Thus, the number of functions that can be registered is limited only by heap memory.

The code in the atexit function should not contain any dependency on any DLL which could have already been unloaded when the atexit function is called.

To generate an ANSI-compliant application, use the ANSI-standard atexit function (rather than the similar_onexit function).

看来编译器通过atexit来实现对b1析构函数的调用。f1等因为无法取得private的析构函数地址导致无法编译。但b1虽然是在类外初始化,但它毕竟还是Bar的成员变量,自然能够访问Bar的其它函数,包括析构函数。当然,我们也可以把b1的初始化放到Bar的构造函数中,虽然我们不提倡这种做法。至此,开始的问题的答案也就出来了。

那么静态成员变量或者全局静态变量的析构函数在何处调用呢?在析构函数中设置断点,看到Call Stack:

Name

Lang

TestCpp.exe!Bar::~Bar()  Line 20

C++

TestCpp.exe!`dynamic atexit destructor for 'Bar::b1''()  + 0x28 bytes

C++

msvcr80d.dll!doexit(int code=0, int quick=0, int retcaller=0)  Line 553

C

msvcr80d.dll!exit(int code=0)  Line 398 + 0xd bytes

C

TestCpp.exe!__tmainCRTStartup()  Line 610

C

TestCpp.exe!wmainCRTStartup()  Line 414

C

可以看出静态变量的析构函数是在main退出后才调用的。

阅读(597) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~