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

忘了什么时候起,脑子里就存在了这样的观点:

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;
}


相关的东西似乎还有一些,一时找不到,以后有时间再补充。

原文链接: https://www.cnblogs.com/yedaoq/archive/2011/05/19/2051382.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

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

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/25745

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午3:31
下一篇 2023年2月8日 上午3:32

相关推荐