1. 程式人生 > >淺析智慧指標

淺析智慧指標

我們知道c和c++相對於其他程式語言是相當自由的語言,給了使用者很大的許可權,比較信任使用者!它允許使用者自由分配計算機記憶體,然後使用者需手動釋放,但是這就帶來了一定的風險,要知道記憶體要是申請了不手動釋放,這塊記憶體就不會作為空閒空間來供以後使用,可想而知,編寫程式要是申請的記憶體太多(當然現在編譯器都是比較智慧的,有一定的記憶體保護機制),不釋放,就可能導致主機可用空間不足,最終結果就是宕機重啟!!!
作為向c語言自身來說,就有一些缺陷,現在我們看一個例子:

A:
int * getspace(){
	static int a[100] ; 
	return a ;
}
B:
int * getspace(){ int *a = malloc(100); return a ; }

這兩個函式的功能都是相同的都是返回一個長度為100的int陣列,但相信大家都會發現一個問題,A函式是不需要手動釋放記憶體的,因為static變數的生命週期和程式的生命週期是一樣的,而B函式它malloc的記憶體必須通過free 釋放掉,而函式就是對外開放的介面,使用者只需要學會用他能實現的功能就行,不需理解它內部實現,這就是非常危險的!!!要是設計一個應用程式函式都像B函式那樣寫,那就涼了!
還有在c++中,當我們在new 一個物件時,在最後,必須呼叫delete釋放,但是這樣真的能解決問題嗎???肯定不能呀!

#include<iostream>
#include<stdlib.h>
using namespace std;
class A{
private:
	int a ;
public:
	A(){}
	~A(){}
};
int main(){
	
	A * s = new A();
	while(1){
		cout<<"好好學習,遠離王者"<<endl;
	}
	delete s ;
}

比如說上面一個簡單的程式,執行時,在迴圈除它就不會退出了,然後我們執行強制退出,那程式是不會執到delete那塊的,所以就記憶體洩漏了!
所以,總的來說,無論是new和delete還是malloc 和free都不是保險可行的記憶體保護策略!
所以在c++中就有了專門防止記憶體洩漏的方法,在c++98之前,用的是auto_ptr,但隨著c++的發展,這種保護方法被開發者逐漸棄用,我今天要說的是另外三種現在比較通用的新的c++智慧指標方法,是c++11新特性。
shared_ptr //可以實現相同型別指標之間的相互賦值!
unique_ptr //對於某一物件特有的指標,不能實現指標之間的相互賦值!
weak_ptr //通常和shared_ptr 一起使用,是shared_ptr 的一種弱引用(非擁有:當引用的物件活著的時候不一定存在。僅僅是當它自身存在的時的一個引用),在使用時轉換成shared_ptr。
三種方法都包含在memory.h標頭檔案中其用法示例如下:

#include<iostream>
#include<memory>
#include<mcheck.h>
using namespace std;
class A{
public:
	A()	{
		a++ ;
		cout<<"build"<<"  "<<a<<endl;}
	~A(){
		a-- ;
		cout<<"destroy"<<"  "<<a<<endl;
	}
    void say(){
        cout<<"away from kingdom game"<<endl ;
    }
private:
	static int a ;
};

int A::a = 0 ;
int main(){
//檢驗是否記憶體洩漏 
    mtrace();
	shared_ptr<A>demo1(new A);
	shared_ptr<A>demo2(new A);
	weak_ptr <A>demo3 = demo1;
    demo1->say();
    demo2->say();
    auto s= demo3.lock();
    demo1->say();
    s->say();
 }

執行過程截圖:
在這裡插入圖片描述

可以發現,用上智慧指標,並沒有造成記憶體洩露問題。智慧指標用的時候就和普通指標的用法差不多。它內部實現過載了*和->運算子。
以上程式中weak_ptr作為shared_ptr的引用,在使用時需要轉化為shared_ptr。
還有unique_ptr的用法,和shared_ptr差不多,但是不能實現像指標那樣互相賦值的操作,它是一個物件特有的指標,其他unique_ptr型別的指標不能再指向該物件。用法如下:

#include<stdio.h>
#include<iostream>
#include<memory>
using namespace  std;
class A{

private: 
    static int a ;
public:

    A(){
        a++ ;
        cout<<"the demo built"<<a<<endl ;
    }
    ~A(){
        a-- ;
        cout<<"the demo destroy"<<a<<endl ;
    }
    void say(){
        cout<<"demo"<<endl;
    }
};
int A::a = 0;
int main(){

    cout<<"-------------------unique ptr----------------"<<endl ;
    unique_ptr <A>demoa(new A);
    unique_ptr <A>demob(new A);
    //這一步是錯誤的,不能互相賦值。
    // unique_ptr democ = demob;
    demoa->say();
    demob->say();
}

嗯,現在,就說這麼多吧!強引用和弱引用以及迴圈引用等概念還不是很熟。後面少玩遊戲,多學習!要學的還是比較多的!