static unique_ptr 两次调用析构函数
static unique_ptr calls destructor twice
我使用单例模式,returns 引用 unique_ptr 解引用。这是代码,
#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;
}
我原以为 class 的析构函数只会调用一次,但尽管构造函数调用一次,析构函数调用两次,这里是输出,
main starts!
Lazy::Lazy() 0xb1ec20
auto state = Settings::lazy() 0x7ffe17ae18b8
main ends!
Lazy::~Lazy() 0x7ffe17ae18b8
Lazy::~Lazy() 0xb1ec20
为什么析构函数调用了两次?甚至第二次调用这个地址也是不同的。
因为你有 2 个单例实例,并且都被销毁了。
您必须有 2 个单例的原因是,当您获得单例时 auto state = Settings::lazy();
会创建一个副本。您可能会返回参考,但 state
不是参考,因此会创建一个副本。
制作 state
参考可解决问题:auto& state = Settings::lazy();
Rakete1111 解决方案是正确的,但您可能还想删除单例的复制构造函数和复制赋值。这样你就可以防止这样的错误发生。
单例 class 必须禁用任何 copy/move 构造函数和 assignment/move 运算符。
否则这不是单例。
因此,
Lazy(Lazy &) = delete;
Lazy(Lazy &&) = delete;
Lazy &operator=(Lazy &) = delete;
Lazy &operator=(Lazy &&) = delete;
那么以下将是唯一有效的操作:
auto& state = Settings::lazy();
我使用单例模式,returns 引用 unique_ptr 解引用。这是代码,
#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;
}
我原以为 class 的析构函数只会调用一次,但尽管构造函数调用一次,析构函数调用两次,这里是输出,
main starts!
Lazy::Lazy() 0xb1ec20
auto state = Settings::lazy() 0x7ffe17ae18b8
main ends!
Lazy::~Lazy() 0x7ffe17ae18b8
Lazy::~Lazy() 0xb1ec20
为什么析构函数调用了两次?甚至第二次调用这个地址也是不同的。
因为你有 2 个单例实例,并且都被销毁了。
您必须有 2 个单例的原因是,当您获得单例时 auto state = Settings::lazy();
会创建一个副本。您可能会返回参考,但 state
不是参考,因此会创建一个副本。
制作 state
参考可解决问题:auto& state = Settings::lazy();
Rakete1111 解决方案是正确的,但您可能还想删除单例的复制构造函数和复制赋值。这样你就可以防止这样的错误发生。
单例 class 必须禁用任何 copy/move 构造函数和 assignment/move 运算符。
否则这不是单例。
因此,
Lazy(Lazy &) = delete;
Lazy(Lazy &&) = delete;
Lazy &operator=(Lazy &) = delete;
Lazy &operator=(Lazy &&) = delete;
那么以下将是唯一有效的操作:
auto& state = Settings::lazy();