首先要知道智慧型指標是用來解決什麼問題的,首先我們先看下面這段**
void func(int *p)
delete sp;
}
這個函式有乙個很大的問題,如果傳入的引數p為空,遇到 if 語句就命中之後就會丟擲異常,程式中斷。那麼指標sp指向開闢的記憶體沒有釋放,導致記憶體洩漏。有什麼方法可以來解決這個問題?
棧:系統開闢記憶體,系統釋放;堆:手動開闢記憶體,手動釋放。那麼如果能對堆上空間實現使用者分配、系統自行**的機制,就不用擔心記憶體洩露的問題了。
智慧型指標的思想:定義乙個類來封裝資源的分配和釋放,在建構函式完成資源的分配和初始化,在析構函式中完成資源的清理和釋放,可以保證資源的正確使用和釋放。(資源指的是堆上資源)
看下面這段**:
#includetemplate class smart_ptr
~smart_ptr()//析構函式
t& operator*()//*運算子過載
t* operator->()//->運算子過載
private:
t *mptr;
};int main()
smart_ptrsp2 = sp1;這句**會釋放同一塊記憶體兩次,導致程式出錯。
這裡介紹四個智慧型指標auto_ptr
1、auto_ptr(已經被摒棄)
實現一:不帶標記的auto_ptr(所有權唯一)
smart_ptr(const smart_ptr& rhs)//拷貝建構函式
smart_ptr& operator=(const smart_ptr& rhs)//賦值運算子過載
return *this;
} t& operator*()
t* operator->()
private:
void release()const
t *mptr;
};int main()
問題:*sp1 = 20; sp1指標指向已經為null,對其解引用訪問了保留區的資料,程式出錯。
實現二:帶有標記的auto_ptr(釋放權唯一,管理權不唯一),即可以多個auto_ptr管理同一片記憶體,但是只能有乙個指標釋放該片記憶體。怎麼確定是哪個指標能釋放呢?在成員變數中加入乙個標誌變數flag,flag為true則有釋放權,flag為false則沒有釋放權。那麼就牽扯釋放許可權轉移的問題,概括來說就是舊智慧型指標擁有的許可權,那麼新智慧型指標也擁有。舊智慧型指標沒有的許可權,那麼新智慧型指標也沒有。
這個功能的實現:new flag = old flag; old flag = false;
#includetemplateclass smartptr
smartptr(const smartptr& rhs) :mptr(rhs.mptr)
smartptr& operator = (const smartptr& rhs)
return *this;
} ~smartptr()
mptr = null;
} t& operator*()
t* operator->()
private:
t* mptr;
mutable bool flag;//是否擁有釋放權
};void func(smartptrsp)//true
{}int main()
問題:根據管理權原則一,若舊智慧型指標有釋放權,則新智慧型指標將釋放權拿走,舊釋放權false。那麼如果這個新智慧型指標只是乙個臨時量,隨著生存週期的到來也隨之消失,那塊被管理的記憶體豈不是莫名其妙就被釋放了
2、scope_ptr(管理權唯一,釋放權唯一)在auto_ptr中,因為設計的問題,導致在使用拷貝建構函式和 賦值運算子的可過載函式時,發生了訪問 空指標、野指標的情況。為了規避這些情況,scoped_str在設計的時候就直接遮蔽了 拷貝建構函式 和 賦值運算子過載函式。
#includetemplateclass scope_ptr
~scope_ptr()
t& operator*()
t* operator->()
private:
scope_ptr(const scope_ptr&);
scope_ptr& operator=(const scope_ptr&);
t* mptr;
};int main()
問題: scoped_ptr的原則也是「管理權唯一,釋放權唯一」,因為遮蔽了 拷貝建構函式 和 賦值運算子過載函式,所以不可能通過這兩種方式去 使得兩個及以上的指標指向同一片記憶體,但是仍然避免不了人為的操作,如sp1和sp2;即初始化兩個scope_ptr指向同一片記憶體,當其中乙個指標釋放了該記憶體,另乙個再想去修改記憶體的內容的話程式就會崩潰
3、shared_ptr(管理權不唯一,釋放權不唯一)
shared_ptr是基於「引用計數」實現的,多個shared_ptr可指向同一片記憶體,並且它們維護著共享的引用計數器——記錄著指向同一片記憶體的shared_ptr物件的個數。當最後乙個指向某一片記憶體的shared_ptr物件也銷毀之後,會自動銷毀掉該片記憶體。shared_ptr很好地解決了 多個智慧型指標指向一塊記憶體塊時, 析構時程式崩潰 的情況。
引用計數器:我們只需要乙個 引用計數器物件,這個物件中就儲存了所有關於記憶體引用的資訊。
}void delref(void* mptr)//刪除
else
}} int getref(void* mptr)//獲取
else
}private:
class node;
std::vector::iterator find(void* mptr)//使用迭代器查詢
}return it;
} class node//結點型別
//建構函式
public:
void* addr;//存放的位址
int ref;//引用計數
}; std::vectorvec;
};
templateclass shared_ptr
shared_ptr(const shared_ptr& rhs) :mptr(rhs.mptr)//拷貝建構函式
shared_ptr& operator = (const shared_ptr& rhs)//賦值運算子過載
mptr = rhs.mptr;
addref();
} return *this;
} ~shared_ptr()
mptr = null;
} t& operator*()
t* operator->()
private:
void addref()
void delref()
int getref()
t* mptr;
static ref_management rm;//引用計數器成員變數象
};//靜態成員變數類外初始化
templateref_management shared_ptr::rm;
int main()
問題:雖然shared_ptr很好地解決了 「多個智慧型指標指向同一塊記憶體時,析構時出錯」的問題,可是同時也帶來了新的問題。shared_ptr之間不能相互引用,否則管理的堆上記憶體塊無法釋放。 c 智慧型指標
auto prt 它是 它所指向物件的擁有者 所以當自身物件被摧毀時候,該物件也將遭受摧毀,要求乙個物件只有乙個擁有者,注意 auto prt 不能使用new 來分配物件給他 include include using namespace std template void bad print au...
c 智慧型指標
很久沒寫部落格了,不知道如何表達了,哈哈.我先介紹一下深淺拷貝.class copy 此時a.ptr和b.ptr指向同乙個物件,當我們delete a.ptr時 b.ptr所指向的物件已經不存在了,要是我們引用b.ptr指向的物件也就會出問題了.深拷貝 把a.ptr所指向的物件拷貝乙份給b.ptr ...
c 智慧型指標
記得前不久有一次面試被問到智慧型指標的實現,當時對智慧型指標只是聽說但沒有了解過,就亂七八糟地說了一遍。今天寫了一遍智慧型指標,用了引用計數的概念。主要思想就是,用乙個新類對原本需要的型別進行了一層封裝,這個新類中儲存了原本的物件指標和乙個引用計數的指標,之所以全部用指標來儲存,就是因為會出現多個新...