Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可以删除局部静态变量吗?_C++_Static_Singleton - Fatal编程技术网

C++ 可以删除局部静态变量吗?

C++ 可以删除局部静态变量吗?,c++,static,singleton,C++,Static,Singleton,我有一个singleton类,它返回指向实例的本地静态的指针,以确保线程安全。现在,如果我没有将析构函数声明为私有,用户可以删除它吗 例如 class Singleton { Singleton(); public: static Singleton *getInstance(); }; Singleton *Singleton::getInstance() { static Singleton inst; return &inst; } /

我有一个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;
}

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

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

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

Singleton& Singleton::getInstance()
{
    static Singleton inst;
    return inst;
}
现在,如果我没有将析构函数声明为私有,用户可以删除它吗

是的,用户可以删除它

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

  • 将析构函数设置为私有
  • 更改
    getInstance()
    的返回类型以返回引用


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

    auto& singleton = Singleton::getInstance();
    delete &singleton; // undefined behaviour
    
    如果您将析构函数设置为私有,则他们可以尝试使用如下邪恶代码来消除该限制:

    delete (void*)(&singleton); // undefined behaviour
    
    事实上,他们也可能试图在指针上调用
    free
    ,这更为邪恶:

    free(&singleton); // undefined behaviour
    
    您可能会认为,如果函数返回指针,则更可能发生此类事故。然后,经验丰富的C++开发人员永远不会尝试<代码>删除<代码>或<代码>免费> /代码>如果没有安全性和必要性,不进行双重检查;我想说的是,如果您必须处理那些试图显式删除从Singleton实例函数返回的内容的程序员,那么无论如何,您都会遇到更大的代码质量问题


    也就是说,使
    getInstance
    返回指针或使析构函数非私有都不会带来任何好处。通过返回引用而不是指针并将析构函数设置为私有,您只会获得一点安全奖励和一些额外的可读性。

    在这种情况下不是这样,因为
    new
    没有分配任何内容。您经常意外删除指针吗?因为没有一种通用的方法可以防止这种情况。可能返回一个引用而不是指针。用户为什么要这样做?一切都可能被破坏,如果你删除了一些你不拥有的东西,你就会得到你应得的;)所以删除一个没有分配“new”的对象是不可行的?我对用户的行为不感兴趣“你不应该这样做”不是答案如果析构函数是私有的,那么对
    delete
    的调用不会编译。@如果它是从Singleton的成员函数调用的,它会编译。@NeilButterworth是的,当然。但并非如示例中所示,来自
    void foo()
    。关键是,如果它不编译,它就不可能是UB。@juan是的,但是OP可以在以后添加另一个成员函数,我想他们正在询问一种铁一般的方法来防止不适当的删除。但这可能是错误的。用户可以随时获取引用的地址并将其删除,如果他们愿意的话+1尽管如此,第6行中缺少指示灯的类型。
    free(&singleton); // undefined behaviour