我今天早上和一位同事就静态变量初始化顺序进行了讨论.他提到了Nifty/Schwarz计数器,我(有点)感到困惑.我理解它是如何工作的,但我不确定这在技术上是否符合标准.
假设以下3个文件(前两个是来自更多C++习语的 copy-pasta ):
//Stream.hpp
class StreamInitializer;
class Stream {
friend class StreamInitializer;
public:
Stream () {
// Constructor must be called before use.
}
};
static class StreamInitializer {
public:
StreamInitializer ();
~StreamInitializer ();
} initializer; //Note object here in the header.
Run Code Online (Sandbox Code Playgroud)
//Stream.cpp
static int nifty_counter = 0;
// The counter is initialized at load-time i.e.,
// before any of the static objects are initialized.
StreamInitializer::StreamInitializer ()
{
if (0 == nifty_counter++)
{
// Initialize Stream …Run Code Online (Sandbox Code Playgroud) 我有两个函数本地静态对象,一个和两个.一个人的构造函数和析构函数都通过GetTwo()访问两个:
#include <iostream>
struct One;
struct Two;
const One& GetOne();
const Two& GetTwo();
struct Two {
const char* value = "It's two!";
Two() { std::cout << "Two construct" << std::endl; }
~Two() { std::cout << "Two destruct" << std::endl; }
};
struct One {
One() {
std::cout << "One construct" << std::endl;
const char* twoval = GetTwo().value;
std::cout << "twoval is: " << twoval << std::endl;
}
~One() {
std::cout << "One destruct" << std::endl;
const char* twoval = GetTwo().value; …Run Code Online (Sandbox Code Playgroud) 是否可以在真正需要时初始化Singleton的实例?
考虑从着名的"设计模式"中获取的这种模式:
class Singleton {
public:
static Singleton* Instance();
protected:
Singleton();
private:
static Singleton* _instance;
}
Singleton* Singleton::_instance = 0; // unit.cpp
static Singleton* Singleton::Instance() {
if (_instance == 0) {
_instance = new Singleton;
}
return _instance;
}
Run Code Online (Sandbox Code Playgroud)
现在,我认为那里的模式存在问题,如果有人希望将库中的Singleton提供给其他人:如果用户Singleton::Instance()在初始化_instance之前从另一个编译单元调用(例如在静态数据成员初始化期间),然后跟随调用Singleton::Instance()可能会创建Singleton的另一个实例,并产生不需要的结果,因为_instance可能首先被初始化为0.
我认为一种解决方案是以这种方式初始化_instance:
Singleton* Singleton::_instance = Singleton::Instance();
Run Code Online (Sandbox Code Playgroud)
无论如何,这使得初始化对于那些不需要调用Singleton :: Instance()来初始化其静态数据的人来说不是"懒惰".
是否有更好的解决方案,以便在需要Singleton实例时可以进行初始化?
创建一个所有成员(属性,函数)都是静态的类的(目标)缺点是什么?特别是与命名空间的使用相比?或者您更愿意创建全局变量/函数?
我喜欢创建静态属性,因为我发现它们"更整洁".(我确切地知道它们来自哪里等等)我对命名空间不是很熟悉.而且我不舒服,在所有的全局变量,因为我不是很熟悉C语言的关键字,例如extern和static.
此外,如果我们考虑班级
class MyStaticClass
{
private:
static int x;
static double y;
public:
static float s;
static double weatherForecast(unsigned int, char);
};
Run Code Online (Sandbox Code Playgroud)
和命名空间
namespace MyNamespace
{
int x;
double y;
float s;
double weatherForecast(unsigned int, char);
}
Run Code Online (Sandbox Code Playgroud)
在通话MyStaticClass::weatherForecast和通话之间是否存在差异(性能方面)MyNamespace::weatherForecast?
阅读/写作MyStaticClass::s和阅读/写作之间是否存在差异(表现方面)MyNamespace::s?
如果使用类而不是主要类型,上述问题的任何答案都会改变吗?