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 之前。

posted @ 2021-03-11 14:09  kouei_kou  阅读(199)  评论(0编辑  收藏  举报