gpt4 book ai didi

c++ - 单例被构造两次

转载 作者:搜寻专家 更新时间:2023-10-31 01:05:56 25 4
gpt4 key购买 nike

我有以下代码:

#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include <memory>

class Logger : public std::ofstream
{
public:
explicit Logger(std::string const& filename = "log.txt"):
std::ofstream(filename.c_str())
{
assert(*this);

*this << "-- log file start --\n" << std::endl;
}

Logger::~Logger()
{
*this << "\n-- log file end --" << std::endl;

this->close();
this->clear();
}
};

Logger logger;

template<class T>
class NotCopyable
{
public:

NotCopyable() { }
~NotCopyable() { }

private:

NotCopyable(NotCopyable const&);
NotCopyable const& operator=(NotCopyable const&);
};

template<class T>
class Singleton : public NotCopyable<Singleton<T> >
{
public:

static T& GetInstance()
{
if (!instance)
{
logger << "Initialize Singleton" << std::endl;

instance.reset(new T());
}

return *instance;
}

protected:

Singleton() { }
virtual ~Singleton() { }

private:

static std::unique_ptr<T> instance;
};

template<class T>
std::unique_ptr<T> Singleton<T>::instance;

class Factory : public Singleton<Factory>
{
public:

Factory() { logger << "Factory constructor" << std::endl; }
~Factory() { logger << "Factory destructor" << std::endl; }

void Blargl() { logger << "Blargl" << std::endl; }

};

bool DoStuff()
{
Factory::GetInstance().Blargl();

return true;
}

bool Thingy = DoStuff();

int main(int, char*[])
{
logger << "Start main()" << std::endl;

Factory::GetInstance().Blargl();

logger << "End main()" << std::endl;
}

输出如下:

-- log file start --

Initialize Singleton
Factory constructor
Blargl
Start main()
Initialize Singleton
Factory constructor
Blargl
End main()
Factory destructor

-- log file end --

我觉得自己很愚蠢,但不明白为什么工厂要 build 两次而不是一次。这是怎么回事?

最佳答案

我尝试运行您的代码,结果与您在 OSX、Apple llvm 5.0 上描述的行为相同。
如果您在 GetInstance() 方法中定义静态实例变量,它工作正常:

static T& GetInstance()
{
static std::unique_ptr<T> instance
if (!instance)
{
logger << "Initialize Singleton" << std::endl;

instance.reset(new T());
}

return *instance;
}

我认为您的代码中存在的问题是 Singleton::instance 在其声明点(默认构造函数)的初始化与 GetInstance() 方法中的赋值之间未指定的执行顺序。
所以,如果我说的是对的,执行顺序可能是这样的:

  1. GetInstance()来自 DoStuff() 的电话打电话
  2. Singleton<Factory>::instance 的默认构造
  3. GetInstance()内拨main()

编辑:用下面的代码测试了我的理论:

template <typename T>
class Ptr {
public:
Ptr()
: p() {
std::cout << "Initalizing Ptr" << std::endl;
}

std::unique_ptr<T> p;
};



template<class T>
class Singleton : public NotCopyable<Singleton<T>> {
public:
static T& GetInstance()
{
if (!instance.p)
{
std::cout << "Initalizing Singleton" << std::endl;
logger << "Initialize Singleton" << std::endl;
instance.p.reset(new T());
}
return *instance.p;
}

protected:
Singleton() { }
virtual ~Singleton() { }

private:
static Ptr<T> instance;
};

template<class T>
Ptr<T> Singleton<T>::instance;

输出:

  1. 初始化单例
  2. 初始化Ptr
  3. 初始化单例

关于c++ - 单例被构造两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21785521/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com