C++全局变量初始化的一点总结
作者:网络转载 发布时间:[ 2015/3/10 11:20:51 ] 推荐标签:C++ 软件开发 函数
Nifty counter.
完美一点的解决方案是 Nifty counter, 现在 GCC 采用的是这个做法[3]。假设现在需要被别处引用的全局变量为 x, Nifty counter 的原理是通过头文件引用,在所有需要引用 x 的地方都增加一个 static 全局变量,然后在该 static 变量的构造函数里初始化我们所需要引用的全局变量 x,在其析构函数里再清理 x,示例如下:
// global.h
#ifndef _global_h_
#define _global_h_
extern X x;
class initializer
{
public:
initializer()
{
if (s_counter_++ == 0) init();
}
~initializer()
{
if (--s_counter_ == 0) clean();
}
private:
void init();
void clean();
static int s_counter_;
};
static initializer s_init_val;
#endif
相应的 cpp 文件:
// global.cpp
#include "global.h"
static X x;
int initializer::s_counter_ = 0;
void initializer::init()
{
new(&x) X;
}
void initializer::clean()
{
(&x)->~X();
}
代码比较直白,所有需要引用 x 的地方都需要引用 global.h 这个头文件,而一旦引入了该头文件,一定会引入 initializer 类型的一个静态变量 s_init_val, 因此虽然不同编译单元间的初始化顺序不确定,但他们都肯定包含有 s_init_val,因此我们可以在 s_init_val 的构造函数里加入对 x 的初始化操作,只有在第一个 s_init_val 被构造时才初始化 x 变量,这可以通过 initializer 的类静态变量来实现,因为 s_counter_ 的初始化是静态初始化,能保证在程序加载后完成了。
初始化 x 用到了 placement new 的技巧,至于析构,那是简单粗暴地直接调用析构函数了,这一段代码里的技巧也许有些难看,但都是合法的,当然,同时还有些问题待解决:
首先,因为 x 是复杂类型的变量,它有自己的构造函数,init() 函数初始化 x 之后,程序初始化 x 所在的编译单元时,x 的构造函数还会被再调用一次,同理 x 析构函数也会被调用两次,这显然很容易引起问题,解决的方法是把 x 改为引用:
// global.cpp
#include "global.h"
static char g_dummy[sizeof(X)];
static X& x = reinterpret_cast<X&>(g_dummy);
int initializer::s_counter_ = 0;
void initializer::init()
{
new(&x) X;
}
void initializer::clean()
{
(&x)->~X();
}
其中 static X& x = reinterpret_cast<X&>(g_dummy); 这一行是静态初始化,因为 g_dummy 是编译时确定了的,而 x 只是一个强制转化而来的引用,编译器不会生成调用 x 构造函数和析构函数的代码。通过上面的修改,这个方案已经比较完美了,但遗憾的是它也不是 正确的,这个方案能正确工作的前提是:所有引用 x 的地方都会 include 头文件 global.h,但如果某一个全局变量 y 的初始化函数里没有直接引用 x, 而是间接调用了另一个函数 foo,而 foo 里引用了 x,此时可能出错了,因为 y 所在的编译单元里并没有直接引用 x,因此很有可能没有 include 头文件 global.h,那么 y 的初始化很有可能在 x 之前。。。
这个问题在 gcc c++ 的标准库里也没有得到解决,有兴趣的可以看看这个讨论。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南