【问题标题】:static unique_ptr calls destructor twicestatic unique_ptr 两次调用析构函数
【发布时间】:2016-03-26 21:24:03
【问题描述】:

我使用单例模式返回对 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;
}

我原以为类的析构函数只会调用一次,但是虽然构造函数调用了一次析构函数调用了两次,但这是输出,

main starts!
Lazy::Lazy() 0xb1ec20
auto state = Settings::lazy() 0x7ffe17ae18b8
main ends!
Lazy::~Lazy() 0x7ffe17ae18b8
Lazy::~Lazy() 0xb1ec20

为什么析构函数调用了两次?甚至第二次调用这个地址也不一样。

【问题讨论】:

  • auto state = Settings::lazy(); 调用内部没有任何跟踪输出的自动复制构造函数。如果你真的想要一个单例,创建一个私有的,你会看到错误。
  • 为什么要使用unique_ptr?还不如只有一个静态对象。
  • 我建议看看这个答案:stackoverflow.com/a/1008289/3807729
  • 另外你真的应该把你的 using 声明 after 所有的 includes 因为你让这些符号对后面的头文件可见声明。
  • 不,在第一次调用函数之前,不会在函数中构造静态。此外,静态对象的构造保证在第一次调用时是线程安全的(静态对象构造时)。

标签: c++ c++11 singleton lazy-loading unique-ptr


【解决方案1】:

因为您有 2 个单例实例,并且都被销毁了。

之所以需要 2 个单例,是因为当您获得单例 auto state = Settings::lazy(); 时,会创建一个副本。您可能会返回参考,但 state 不是参考,因此会创建一个副本。

state 设为引用可解决问题:auto&amp; state = Settings::lazy();

【讨论】:

【解决方案2】:

Rakete1111 解决方案是正确的,但您可能还想删除单例的复制构造函数和复制分配。这样您就可以防止此类错误的发生。

【讨论】:

    【解决方案3】:

    单例类必须禁用任何复制/移动构造函数和赋值/移动运算符。 否则这不是单例。
    因此,

    Lazy(Lazy &) = delete;
    Lazy(Lazy &&) = delete;
    Lazy &operator=(Lazy &) = delete;
    Lazy &operator=(Lazy &&) = delete;
    

    那么以下将是唯一有效的操作:

    auto& state = Settings::lazy();
    

    【讨论】:

      猜你喜欢
      • 2010-12-29
      • 2023-03-31
      • 1970-01-01
      • 2014-10-25
      • 2015-02-25
      • 2012-11-21
      • 1970-01-01
      • 2014-05-18
      • 2013-03-07
      相关资源
      最近更新 更多