单例行为相关查询

use*_*354 5 c++ templates design-patterns smart-pointers

我知道这是关于单身人士模式的非常愚蠢的问题,但它仍然是面试官的首选.你可以在下面的代码片段中告诉我吗?

(1)删除单例对象后,为什么我仍然可以调用show()方法,它工作正常.

delete obj;
obj=NULL;
obj->show();
Run Code Online (Sandbox Code Playgroud)

(2)创建obj1对象后,为什么我无法打印acquire_lock和release_lock函数的内容,即使打印状态"一次"也会打印一次,如果我们增加计数器i而不是2则只打印1,为什么?

Foo *obj1=MySingleton<Foo>::GetInstance();
Run Code Online (Sandbox Code Playgroud)

(3)使用unique_ptr和singleton对象会产生任何负面影响.

代码段:

#include <iostream>
#include <fstream>
#include <memory>
#include <string>

using namespace std;

static int i;

class Lock
{
public:
    Lock(){};
    ~Lock(){};

    void acquire_lock()
    {
        cout<<"aquired lock for class";
    }

    void release_lock()
    {
        cout<<"released lock for class";
    }

};

class Foo
{
public:
    void show()
    {
        cout<<"\ndone\n"; 
    }
};

template <class T>
class MySingleton
{
protected:

    MySingleton() {}

private:

    //holds one and only object of MySingleton
    static T* m_pOnlyOneInstance;
    MySingleton(const MySingleton <T> &) {};
    MySingleton <T> & operator=(const MySingleton <T> &) {};
    ~MySingleton() {};

public:

    static T * GetInstance();

    void foo()
    {
        cout<<"Mohan";
    }
};


template <class T>
T*  MySingleton<T>::GetInstance()
{
    Lock lock;
    if (m_pOnlyOneInstance == NULL)
    {  
        lock.acquire_lock();
        cout<<"one Time"<<endl;  
        i++; 
        if(m_pOnlyOneInstance == NULL)
        {
            m_pOnlyOneInstance = new T();
        }
        lock.release_lock();
    }  
    return m_pOnlyOneInstance;
}

template <class T> T* MySingleton<T> :: m_pOnlyOneInstance=NULL;

int main()
{
    //std::unique_ptr <Foo> obj (MySingleton<Foo>::GetInstance());
    Foo *obj=MySingleton<Foo>::GetInstance();    
    //obj->show();
    delete obj;
    obj=NULL;
    obj->show();
    cout<<"\ncalling again\n";
    Foo *obj1=MySingleton<Foo>::GetInstance();
    obj1->show();
    cout<<"i="<<i;  
    return 1;   
}
Run Code Online (Sandbox Code Playgroud)

注意:锁相关功能仅为虚拟实现.

Eel*_*lke 0

(1) 如果实际使用 obj 来执行调用或在调用内,则调用将失败。

首先,调用 self 是对非虚函数的调用,因此不需要 obj 指针来查找该函数。编译器在编译时就已经确定要调用哪个函数。

其次,该函数不访问类的任何成员变量,因此虽然它确实收到了 NULL 的 this 指针,但它实际上从不使用它。

顺便说一句,这段代码似乎试图使用 MySingleton 模板将其他类转换为单例,但事实并非如此,因为它不会阻止通过其他方式复制或实例化对象,因此它不是真正的单例。它唯一做的就是始终返回相同的指针。

顺便说一句,第二次调用会MySingleton<Foo>::GetInstance()返回您之前删除的指针的副本delete objobj删除后设置为 NULL,但 MySingleton 模板中的原始指针仍然指向已删除的对象,因此第二次调用 GetInstance 将很高兴地返回现在无效的指针。