你能删除本地静态变量吗?

时间:2017-04-21 19:34:26

标签: c++ static singleton

我有我的单例类,它返回指向实例的本地静态的指针以确保线程安全。现在,如果我没有将析构函数声明为私有,那么用户可以将其删除吗?

对于前。

class Singleton
{
    Singleton();
    public:
    static Singleton *getInstance();

};

Singleton *Singleton::getInstance()
{
    static Singleton inst;
    return &inst;
}

// in user code
void foo()
{
    Singleton *inst = Singleton::getInstance();
    // do its stuff

    //accidentally delete instance here?! 
    // Should I have private destructor?
    delete inst;
}

3 个答案:

答案 0 :(得分:5)

如果在析构函数设置为私有的情况下尝试删除foo中的指针,则会导致编译错误,因为析构函数不可访问。如果在delete的成员或朋友中调用了Singleton,那么它仍然会编译。这就是说delete未使用new分配的指针是未定义的行为,因此我们应该尝试将其设置为用户不会偶然尝试调用delete的位置。

可以阻止这种情况的一种方法是返回引用而不是指针。这样,您的用户甚至不会尝试调用delete,因为他们正在处理非指针类型。

class Singleton
{
    Singleton() {};
    public:
    static Singleton& getInstance();
};

Singleton& Singleton::getInstance()
{
    static Singleton inst;
    return inst;
}

答案 1 :(得分:3)

正如那句老话所说的那样,C ++可以防范墨菲,而不是对抗马基雅维利。您可以通过获取其地址来获取所有的指针,然后尝试删除它。因此,即使您的getInstance函数返回Singleton&而不是Singleton*,也不会阻止类的用户执行以下操作,从而调用未定义的行为

auto& singleton = Singleton::getInstance();
delete &singleton; // undefined behaviour

如果你将析构函数设为私有,他们可以尝试使用这样的恶意代码来抛弃该限制:

delete (void*)(&singleton); // undefined behaviour

事实上,他们也可能试图在指针上调用free,这更加邪恶:

free(&singleton); // undefined behaviour

如果函数返回指针,你可能会认为这样的事故更可能 。然后,经验丰富的C ++开发人员再也不会尝试deletefree某些东西,而不会仔细检查它是否安全且必要;我会说如果你必须处理那些试图明确删除从Singleton实例函数返回的东西的程序员,那么无论如何你都会遇到更大的代码质量问题。

话虽如此,通过使getInstance返回指针或使析构函数非私有,没有任何结果。通过返回引用而不是指针并使析构函数变为私有,您只需要牺牲一点安全奖励和一些额外的可读性。

答案 2 :(得分:1)

  

现在,如果我没有将析构函数声明为私有,那么用户可以将其删除吗?

是的,用户可以将其删除。

确保他们不容易这样做是你的工作(一个坚定的用户意图颠覆你的意图会找到一种方法)。您可以采取的方向:

  1. 制作析构函数private
  2. 更改getInstance()的返回类型以返回参考。
  3. class Singleton
    {
       public:
    
          static Singleton& getInstance()
          {
             static Singleton theInstance;
             return theInstance;
          }
    
       private:
    
          Singleton(){}
          ~Singleton(){}
    };