我使用单例模式返回对unique_ptr dereference的引用。这是代码,
#include <iostream>
#include <memory>
using std::cout; using std::endl;
using std::unique_ptr;
namespace Settings {
class Lazy {
Lazy() { cout << "Lazy::Lazy() " << this << endl; }
public:
~Lazy() { cout << "Lazy::~Lazy() " << this << endl; }
static Lazy &instance()
{
static unique_ptr<Lazy> lazy(new Lazy);
return *lazy;
}
};
Lazy &lazy()
{ return Lazy::instance(); }
}
int main()
{
cout << "main starts!" << endl;
auto state = Settings::lazy();
cout << "auto state = Settings::lazy() " << &state << endl;
cout << "main ends!" << endl;
return 0;
}
我原以为类的析构函数只会调用一次,但是构造函数调用一次析构函数调用两次,这里是输出,
main starts!
Lazy::Lazy() 0xb1ec20
auto state = Settings::lazy() 0x7ffe17ae18b8
main ends!
Lazy::~Lazy() 0x7ffe17ae18b8
Lazy::~Lazy() 0xb1ec20
为什么析构函数会调用两次?甚至第二次呼叫这个地址也不同。
答案 0 :(得分:4)
因为你有2个单例实例,并且都被破坏了。
你需要2个单身的原因是,当你获得单身auto state = Settings::lazy();
时,会创建一个副本。您可能会返回引用,但state
不是引用,因此会创建副本。
使state
引用可修复问题:auto& state = Settings::lazy();
答案 1 :(得分:1)
Rakete1111解决方案是正确的,但是您可能还想删除单例的副本构造函数和副本分配。这样,您就可以防止发生此类错误。
答案 2 :(得分:1)
Singleton 类必须禁用任何复制/移动构造函数和赋值/移动运算符。
否则这不是单例。
因此,
Lazy(Lazy &) = delete;
Lazy(Lazy &&) = delete;
Lazy &operator=(Lazy &) = delete;
Lazy &operator=(Lazy &&) = delete;
那么以下将是唯一有效的操作:
auto& state = Settings::lazy();