单例行为相关查询

时间:2015-07-12 05:42:56

标签: c++ templates design-patterns smart-pointers

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

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

delete obj;
obj=NULL;
obj->show();

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

Foo *obj1=MySingleton<Foo>::GetInstance();

(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;   
}

注意:锁相关函数只是虚拟实现。

4 个答案:

答案 0 :(得分:2)

  1. 请注意,obj->show()相当于Foo::show(obj)。这两个表达式都将this设置为obj成员函数中show的值。现在,thisNULLshow的设置是什么?没什么,因为你从不引用this
  2. 好吧,想想你首先使用单身模式的全部原因 - 最多只能初始化一次。那一次&#34;一次&#34; print语句位于对象实例化的代码中,因此它自然不会在第一次执行后执行。看看GetInstance的逻辑。如果一个实例不存在,它会实例化该类(乱七八糟......但确实有效),之后实例就存在了。否则,它什么都不做。
  3. 这个问题非常不清楚,但我认为你的意思是&#34;做std::unique_ptr<Foo> obj = MySingleton<Foo>::GetInstance();的负面影响是什么?&#34;正如您在unique_ptr unique_ptr中所看到的,其目的是获取动态分配资源的所有权。当你处理单例对象时,这肯定是。因为资源(在这种情况下是单例实例)在任意数量的调用者之间共享,所以单例类是唯一应该管理实例资源的类 - 这是单例模式的基本不变量。如果您使用obj,只要{{1}}超出范围,它就会自动删除实例,无论您的程序是否在其他地方引用了现已释放的实例。

答案 1 :(得分:1)

这不是删除单例对象的正确方法,您需要编写以下方法以删除实例然后执行您的程序。

Thread.sleep(8000);

这是输出:

为classone Time获取锁定 释放锁定课程 完成

再次打电话 获得了锁定时间的锁定 释放锁定课程 DONE I = 2

答案 2 :(得分:0)

(1) 如果它实际上使用obj来执行呼叫或在呼叫中,则呼叫将失败。

首先,它自己调用非虚函数,因此不需要obj指针来查找函数。编译器已经在编译时计算出要调用的函数。

其次,该函数不访问该类的任何成员变量,因此当它确实收到一个NULL指针时,它实际上从不使用它。

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

其他BTW,对D:\android-sdk\platform-tools>adb remount remount succeeded D:\android-sdk\platform-tools>adb shell root@generic_x86_64:/ # adb install 1.apk adb install 1.apk Invalid APK file: 1.apk 255|root@generic_x86_64:/ # adb push 1.apk /sdcard adb push 1.apk /sdcard error: device offline 1|root@generic_x86_64:/ # 1|root@generic_x86_64:/ # ls ls acct cache charger config d data 的第二次调用会返回您在执行MySingleton<Foo>::GetInstance()时先前删除的指针的副本。删除后delete obj设置为NULL,但MySingleton模板中的原始指针仍然指向已删除的对象,因此第二次调用GetInstance将很高兴地返回现在无效的指针。

答案 3 :(得分:0)

你的单例类应该有一个私有的构造函数和析构函数。当单例的范围结束时,析构函数应该处理任何内存清理,因此不需要显式删除它。当其他对象在删除点之后仍然访问单例时,删除它可能是不安全的。当你执行“删除obj”和“obj = null”时,你可能会得到一个未定义的行为,因为你重载了赋值运算符和析构函数是私有的。