您的位置:首页 > 编程语言 > C语言/C++

C/C++函数中局部对象的构造与析构时机

2011-05-19 19:34 483 查看
忘了什么时候起,脑子里就存在了这样的观点:

1. 局部变量应尽量定义在代码起始处

2. 局部变量的构造是在进入函数时进行的,其时间与局部变量声明的位置无关

我记得这个观点应该来自权威的书籍或某些具有丰富经验,在我看来就如同凡人眼里手持法杖、身着华服的法师一般神圣的开发大牛。这个观点在当时我的看来是如此的权威,以至于素爱折腾的我也在整个大学期间未予质疑。

由于这个特性,我一直以来就有一个疑问,在RAII中,为了保证Critical Section的最小化,岂不是得为此做刻意的函数分割,将Critical Section抽离出来用单独的函数包装。

不过,最近我在看log4cplus的代码时,看到如下的代码段:

do {
::log4cplus::thread::Guard _sync_guard_object(mutex);
this->errorHandler = eh;
} while (0)


这段代码让我对在我脑海里存在了长久时间的观点产生了质疑,如果那是对的,那这里何必用do循环来制造一个子域呢?因此我写了一些代码测试一下:

#include "stdafx.h"
#include <iostream>

using namespace std;

#define mainSizeof main

class obj
{
public:
obj()
{
cout<<"obj construct  ..."<<endl;
}

~obj()
{
cout<<"obj destruct ..."<<endl;
}
};

void LocalVarIniTest1()
{
cout<<"Local Variable Initial Test Function 1 : do{} "<<endl;

int i = 2;

do
{
cout<<"Begin of the loop body ... "<<endl;
obj o;
cout<<"End of the loop body ..."<<endl;
} while (--i);

cout<<"End of Function body 1"<<endl<<endl;
}

void LocalVarIniTest2()
{
cout<<"Local Variable Initial Test Function 2 : {} "<<endl;

{
cout<<"Begin of the loop body ... "<<endl;
obj o;
cout<<"End of the loop body ..."<<endl;
}

cout<<"End of Function body 2"<<endl<<endl;
}

void LocalVarIniTest3()
{
cout<<"Local Variable Initial Test Function 3 : if{} "<<endl;

if(true) {
cout<<"Begin of the loop body ... "<<endl;
obj o;
cout<<"End of the loop body ..."<<endl;
}

cout<<"End of Function body 3"<<endl<<endl;
}

void LocalVarIniTest4()
{
cout<<"Local Variable Initial Test Function 4 : no sub range "<<endl;

obj o;

cout<<"End of Function body 4"<<endl<<endl;
}

void LocalVarIniTest5()
{
obj o;

cout<<"Local Variable Initial Test Function 5 : no sub range "<<endl;

cout<<"End of Function body 5"<<endl<<endl;
}

int mainLocalVarIni()
{
LocalVarIniTest1();
LocalVarIniTest2();
LocalVarIniTest3();
LocalVarIniTest4();
LocalVarIniTest5();

getchar();

return 1;
}



这段程序在VC6上的输出如下:

Local Variable Initial Test Function 1 : do{}

Begin of the loop body ...

obj construct  ...

End of the loop body ...

obj destruct ...

Begin of the loop body ...

obj construct  ...

End of the loop body ...

obj destruct ...

End of Function body 1

Local Variable Initial Test Function 2 : {}

Begin of the loop body ...

obj construct  ...

End of the loop body ...

obj destruct ...

End of Function body 2

Local Variable Initial Test Function 3 : if{}

Begin of the loop body ...

obj construct  ...

End of the loop body ...

obj destruct ...

End of Function body 3

Local Variable Initial Test Function 4 : no sub range

obj construct  ...

End of Function body 4

obj destruct ...

obj construct  ...

Local Variable Initial Test Function 5 : no sub range

End of Function body 5

obj destruct ...

从输出可以简单的得出一些结论:

1. 对象的构造时机取决于它的定义位置,初始化过程不会被编译器提前或延后。

2. 对象的析构在生命期结束(退出定义域)时由编译器自动执行。

3. 循环体内定义的变量会被初始化和析构多次。

4. 域以{}定义,它可以是函数体,do,while,if等复合语句,单独的{}也同样可以定义一个子域。

 

然而,这并非全部,我之前所接触到的说法不应该是空穴来说或是错觉,于是找了找,发现它其实来自C,在C语言中,所有的局部变量都必须定义在函数体的起始位置。创建一个.c文件,然后添加如下代码,该文件将编译失败。

void fun()
{
int a;
a = 1;
int b;

a = 2;
b = 2;
}



相关的东西似乎还有一些,一时找不到,以后有时间再补充。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: