只能生成棧上對象,堆上對象,不能繼承,單例模式

1.設計一個類不能被繼承
2.設計一個類只能在堆上創建對象。
3.設計一個類只能在棧上創建對象
4.單例模式

之所以把這4道題放在一起,是因爲他們有着相似之處。

在C++中,類的對象建立分爲兩種,一種是靜態建立,如A a;
另一種是動態建立,如A* ptr=new A;這兩種方式是有區別的。

靜態建立一個類對象,是由編譯器爲對象在棧空間中分配內存,是通過直接移動棧頂指針,挪出適當的空間,然後在這片內存空間上調用構造函數形成一個棧對象。使用這種方法,直接調用類的構造函數

動態建立類對象,是使用new運算符將對象建立在堆空間中。這個過程分爲兩步,第一步是執行operator new()函數,在堆空間中搜索合適的內存並進行分配;第二步是調用構造函數構造對象,初始化這片內存空間。這種方法,間接調用類的構造函數。


編譯器在爲類對象分配棧空間時,會先檢查類的析構函數的訪問性,其實不光是析構函數,只要是非靜態的函數,編譯器都會進行檢查。如果類的析構函數是私有的,則編譯器不會在棧空間上爲類對象分配內存。

class A
{
public:
    static A* Create()
    {
        return new A();
    }

    //void Destroy()
    //{
    //  delete this;
    //}

    static void Destroy(A* p)
    {
        delete p;
    }

protected: 
    ~A() {}
    A() {}
};



int main()
{
    A* pa = A::Create();
    pa->Destroy();
    //或者
    //A::Destroy(pa);
    return 0; 
}

注意:

如果設計不能繼承的類只需要將上面的構造和析構函數私有即可


只有使用new運算符,對象纔會建立在堆上,因此,只要禁用new運算符就可以實現類對象只能建立在棧上。將operator new()設爲私有即可。代碼如下:

class B
{
public:
    B() {}
    ~B() {}
private:
    void* operator new(size_t sz){}
    void operator delete(void* p) {}
};

寫一個線程安全的單例模式

一般來說,有懶漢和餓漢兩種模式:

相對來說,餓漢比較簡單,因爲在餓漢模式下,在單例類定義的時候就已經定義了一個對象,對類進行了初始化。後面不管哪個線程調用成員函數getInstance(),都只不過是返回一個對象的指針而已。所以是線程安全的,不需要在成員函getInstance中加鎖。
顯然,餓漢的好處就是避免進行線程同步,因爲當訪問量比較大,或者可能訪問的線程比較多時,採用餓漢實現,可以實現更好的性能。而壞處則是未使用就創建了,有點浪費空間,當然這是以空間換時間

//餓漢模式
class Single1
{
public:
    static Single1* getInstance()
    {
        return p;
    }

private:
    Single1()
    {}
private:
    static Single1* p;
};

Single1* Single1::p = new Single1;

而懶漢:故名思義,不到萬不得已就不會去實例化類,也就是說在第一次用到類實例的時候纔會去實例化。因此除了只能創建一個對象也需要考慮多線程同步的問題

class Single
{
public:
    static Single* getInstance()
    {
        if (p == NULL) //避免多次進入,因爲線程同步很耗時
        {
            pthread_mutex_lock(&mutex);
            if (p == NULL)
                return new Single;
            pthread_mutex_unlock(&mutex);
        }
        return p;
    }
private:
    Single() {}

    static Single* p;
    static pthread_mutex_t mutex;
};

Single* Single::p =  NULL;
pthread_mutex_t Single::mutex = PTHREAD_MUTEX_INITIALIZER;

下面是內部靜態變量的懶漢實現

class Single
{
public:
    static Single* getInstance()
    {
        pthread_mutex_lock(&mutex);
        static Single obj; 
        pthread_mutex_unlock(&mutex);
        return &obj;
    }
private:
    Single() {}
    static pthread_mutex_t mutex;
};

pthread_mutex_t Single::mutex = PTHREAD_MUTEX_INITIALIZER;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章