关于Json11源代码中静态全局结构体的疑问
嘿,我来帮你拆解这段Json11里的代码,当初我第一次看这段的时候也琢磨了好一会儿呢!
首先先把你那段截断的代码补全(应该是下面这样):
/* * * * * * * * * * * * * * * * * * * * * Static globals - static-init-safe */ struct Statics { const std::shared_ptr<JsonValue> null = make_shared<JsonNull>(); const std::shared_ptr<JsonValue> t = make_shared<JsonBoolean>(true); const std::shared_ptr<JsonValue> f = make_shared<JsonBoolean>(false); const string empty_string; const vector<Json> empty_vector; const map<string, Json> empty_map; };
这段代码的核心是解决C++里的静态初始化顺序问题,同时实现JSON基础类型实例的全局复用。
我给你逐个拆解每个部分的作用:
null/t/f:这三个是JSON里最基础的null、true、false值的实例,用std::shared_ptr包裹后全局复用。这样每次需要返回JSON null/布尔值时,不用重新创建新对象,直接返回这些指针就行,既省内存又高效。empty_string/empty_vector/empty_map:对应空的JSON字符串、数组、对象的容器实例。当Json11需要返回空的JSON类型时,直接返回这些全局空实例的引用,避免每次创建新的空容器。
而为什么要把这些变量塞进一个Statics结构体里?关键在于注释里的static-init-safe——C++里不同编译单元的全局静态变量初始化顺序是不确定的,如果直接把这些变量定义成全局的,很可能出现某个代码在这些变量初始化前就使用它们的情况,导致未定义行为。
Json11的常规做法是把这个Statics实例放在一个静态函数里,比如:
static const Statics& get_statics() { static Statics s; return s; }
这样一来,Statics里的所有成员会在第一次调用get_statics()时才初始化,而且C++11及以后标准保证静态局部变量的初始化是线程安全的,完美规避了静态初始化顺序的坑。
说白了,这段代码就是用一种安全的方式,提供全局可复用的JSON基础类型实例,兼顾了性能和初始化安全性。
内容的提问来源于stack exchange,提问作者ehds
相关产品推荐
相关产品推荐

