C++ nifty counter idiom 实例学习
C+ 全局变量初始化中的nifty counter idiom的原理参考了以下链接:
https://www.cnblogs.com/catch/p/4314256.html
本文给出一个可以运行的实例,不对之处请批评指正。
/* class_a.h */
#ifndef _class_h_
#define _clsss_h_
#include <iostream>
class A
{
public:
A(int i) :a(i)
{
std::cout << "class A construted." << std::endl;
}
~A()
{
std::cout << "class A deconstruted." << std::endl;
}
int get_value()
{
return a;
}
private:
int a;
};
#endif
/* class_a.cpp */
#include "class_a.h"
/* void */
/* global.h */
#ifndef _global_h_
#define _global_h_
#include "class_a.h"
extern A& 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
/* global.cpp */
#include "global.h"
// need to ensure memory alignment??
static char g_dummy[sizeof(A)];
A& x = reinterpret_cast<A&>(g_dummy);
int initializer::s_counter_ = 0;
void initializer::init()
{
new(&x) A(8);
}
void initializer::clean()
{
(&x)->~A();
}
/* main.cpp */
#include <iostream>
#include "global.h"
int main()
{
std::cout << "x = " << x.get_value() << std::endl;
return 0;
}
编译:
g++ class_a.cpp global.cpp main.cpp
执行结果:
class A construted.
x = 8
class A deconstruted.
总结:
1、A& x = reinterpret_cast<A&>(g_dummy); x 只是一个强制转化而来的引用,编译器不会生成调用 x 构造函数和析构函数的代码。
2、这个方案能正确工作的前提是:所有引用 x 的地方都会 include 头文件 global.h,但如果某一个全局变量 y 的初始化函数里没有直接引用 x, 而是间接调用了另一个函数 foo,再通过 foo 引用了 x,此时就可能出错了,因为 y 所在的编译单元里可能并没有直接引用 x,因此很有可能就没有 include 头文件 global.h,那么 y 的初始化就很有可能发生在 x 之前。