局部静态变量的初始化与异常

1、问题

编程的过程中,思考了一个问题。当一个局部的静态变量使用一个函数的返回值初始化时,如果该函数抛出异常,那么,局部静态变量是否被定义成功,即,如果再次调用包含局部静态变量的函数,抛出异常的函数会不会再次被调用。

2、测试

就此问题,我写了如下的测试程序:

 

3、结果

1、在VC9中:第二次调用TestStatic函数不再抛出异常,即,局部静态变量已经定义成功。

2、在gcc中:第二次调用TestStatic函数依旧抛出异常,即,局部静态变量没有定义成功,需要再次进入定义,实现真正的内存分配空间。

 

对于结果,我更欣赏GNU的方式!

不管喜欢那种方式,测试结果都告诉我们,这段代码并部具有可移植性。VC的方式,让我比较失望,因为,因此而失去了一个通用的编程技巧。然而,知道什么是错的,比知道什么是对的还要重要,难道不是吗?

4、背景与应用

有朋友会问,这样的问题,什么情况下会遇到?

我只用一个比较经典的例子来说明。略微熟悉设计模式的朋友都会知道Singleton模式。一般返回的都是一个具体类的实例。虽说一般情况下构造函数中不要抛出异常,但免不了在某些情况下,可能会抛出异常,尤其是在这种单实例模式的情形下,没有必要一定保持构造函数中一定不抛出异常(stl要求容器中的类的构造函数不要抛出异常),所以,在这种情况下,我们似乎会希望,如果构造不成功,客户函数捕获异常,并修复错误后,再次获得单实例时,希望能够再次进行初始化,而得到一个正确的单实例的引用。然而,在这种情况下,面对两个编译器的测试结果,这段代码并不具有可移植性。

如果,只是如果,GNU编译器的方式是一个规范的话,那么,我们在Singleton模式下,就无需判断返回的对象是否有效,如果发生异常,也无须在实现类中编写弥补的代码,只需要再次重新获得Singleton即可,可以简化代码。但,这只是如果。

 

5、补充

回复 scwinter:

多谢兄弟关注!刚才我测试了一下,启用和未启用异常展开语义,编译的结果是不一样的。又掌握了一个知识点!结果如下:
E:/temp/C++>cl test.cpp
用于 80x86 的 Microsoft (R) 32 位 C/C++ 优化编译器 15.00.30729.01 版
版权所有(C) Microsoft Corporation。保留所有权利。

test.cpp
C:/Program Files/Microsoft Visual Studio 9.0/VC/INCLUDE/xlocale(342) : warning C4530: 使用了 C++ 异常处理程序,但未启用展开语义。请指定 /EHsc
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj

E:/temp/C++>test
exc1:100
TestStatic:0

 

E:/temp/C++>cl test.cpp /EHsc
用于 80x86 的 Microsoft (R) 32 位 C/C++ 优化编译器 15.00.30729.01 版
版权所有(C) Microsoft Corporation。保留所有权利。

test.cpp
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:test.exe
test.obj

E:/temp/C++>test
exc1:100
exc2:100

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值