這篇文章給大家介紹如何使用c++ 智能指針,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
創(chuàng)新互聯(lián)建站長期為成百上千家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為大峪企業(yè)提供專業(yè)的網(wǎng)站設(shè)計、成都網(wǎng)站制作,大峪網(wǎng)站改版等技術(shù)服務(wù)。擁有十余年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。在現(xiàn)代 C++ 編程中,標(biāo)準(zhǔn)庫包含了智能指針(Smart pointers)。
智能指針用來確保程序不會出現(xiàn)內(nèi)存和資源的泄漏,并且是"異常安全"(exception-safe)的。
智能指針定義在頭文件 memory 里的命名空間 std 中。它對于資源獲取即初始化(RAII, Resource Acquisition Is Initialization) 編程理念至關(guān)重要。該理念的目的是保證對象初始化的時候也是資源獲取的時候,從而使對象的所有資源在單行代碼中創(chuàng)建。
實(shí)踐中,RAII 的主要原則就是把任何在堆上分配的資源(比如動態(tài)分配的內(nèi)存或者系統(tǒng)對象的處理)的所有權(quán)提供給在棧上分配的對象(其析構(gòu)函數(shù)包含釋放資源及相關(guān)清理的代碼)。
大多數(shù)時候,當(dāng)你初始化一個原始指針或者資源句柄使其指向?qū)嶋H的資源時,立即將其傳給智能指針。
在現(xiàn)代 C++ 中,原始指針只用于包含在局部作用域,循環(huán)或者工具函數(shù)的小塊代碼中(對性能有要求,并且對資源的所有權(quán)也不容易混淆)。
原始指針和智能指針的聲明比較如下:
void UseRawPointer() { // Using a raw pointer -- not recommended. Song* pSong = new Song(L"Nothing on You", L"Bruno Mars"); // Use pSong... // Don't forget to delete! delete pSong; } void UseSmartPointer() { // Declare a smart pointer on stack and pass it the raw pointer. unique_ptrsong2(new Song(L"Nothing on You", L"Bruno Mars")); // Use song2... wstring s = song2->duration_; //... } // song2 is deleted automatically here.
如上所示,智能指針是一個在棧上聲明的類模板,并由指向分配在堆上的對象的原始指針初始化。當(dāng)智能指針初始化后,它就擁有了原始指針的所有權(quán)。這意味著智能指針需要負(fù)責(zé)原始指針指向的內(nèi)存釋放。智能指針的析構(gòu)函數(shù)包含了 delete 的調(diào)用,并且由于智能指針是在棧上聲明的,其析構(gòu)函數(shù)會在智能指針對象離開作用域時被調(diào)用,即使在棧中發(fā)生了異常。
通過使用指針運(yùn)算符(-> 和 *)訪問被封裝的指針,智能指針類重載了這些運(yùn)算符以返回被封裝的原始指針。
C++ 智能指針的理念類似于在 C# 語言中創(chuàng)建對象的過程:創(chuàng)建對象后讓系統(tǒng)負(fù)責(zé)在正確的時間將其刪除。不同之處在于,沒有獨(dú)立的垃圾回收器運(yùn)行于后臺;內(nèi)存是按照標(biāo)準(zhǔn) C++ 規(guī)范對內(nèi)存進(jìn)行管理的,使運(yùn)行時環(huán)境更加快速和高效。
[!重要]
總是在單獨(dú)的行上創(chuàng)建智能指針,而不是在參數(shù)列表中,從而避免由于特定的參數(shù)列表分配規(guī)則出現(xiàn)一些輕微的內(nèi)存泄漏
以下示例顯示了 C++ 標(biāo)準(zhǔn)庫中的 unique_ptr 是如何封裝指向大型對象的指針的。
class LargeObject { public: void DoSomething(){} }; void ProcessLargeObject(const LargeObject& lo){} void SmartPointerDemo() { // Create the object and pass it to a smart pointer std::unique_ptrpLarge(new LargeObject()); //Call a method on the object pLarge->DoSomething(); // Pass a reference to a method. ProcessLargeObject(*pLarge); } //pLarge is deleted automatically when function block goes out of scope.
上述示例演示了使用智能指針的關(guān)鍵步驟:
將智能指針聲明為局部變量(不要在智能指針上使用 new 或者 malloc 表達(dá)式)。
在類型參數(shù)上,指定被封裝指針指向的對象類型。
將指向由 new 創(chuàng)建的對象的指針傳給智能指針的構(gòu)造函數(shù)。
使用重載的操作符 -> 和 * 來訪問對象。
讓智能指針來 delete 對象。
智能指針在設(shè)計上兼顧了內(nèi)存和性能的高效性。例如,unique_ptr 的數(shù)據(jù)成員是被封裝的原始指針,這意味著 unique_ptr 具有原始指針同樣地大小,4 字節(jié)或者 8 字節(jié)。通過智能指針重載的操作符 -> 和 * 來訪問并不比直接使用原始指針來訪問慢多少。
智能指針有其自己的成員函數(shù),通過 . 來訪問。例如,一些 C++ 標(biāo)準(zhǔn)庫的智能指針有用于重置的成員函數(shù)來釋放對原始指針的所有權(quán)。這可以用于在智能指針超出作用域前釋放智能指針管理的內(nèi)存,看下面的示例:
void SmartPointerDemo2() { // Create the object and pass it to a smart pointer std::unique_ptrpLarge(new LargeObject()); //Call a method on the object pLarge->DoSomething(); // Free the memory before we exit function block. pLarge.reset(); // Do some other work... }
智能指針通常提供了獲取原始指針的方式。 C++ 標(biāo)準(zhǔn)庫中的智能指針包含了成員函數(shù) get 來獲取原始指針。 CComPtr 有公共的類成員 p。通過獲取原始指針,你能夠使用智能指針來管理你自己代碼涉及的內(nèi)存并依然能夠?qū)⒃贾羔槀鬟f給不支持智能指針的代碼。
void SmartPointerDemo4() { // Create the object and pass it to a smart pointer std::unique_ptrpLarge(new LargeObject()); //Call a method on the object pLarge->DoSomething(); // Pass raw pointer to a legacy API LegacyLargeObjectFunction(pLarge.get()); }
以下部分總結(jié)了在 Windows 環(huán)境下不同種類的智能指針,以及如何使用它們。
優(yōu)先使用下列智能指針來封裝原始指針指向的純舊對象(plain old C++ objects,POCO):
unique_ptr
對封裝的原始指針是獨(dú)占的
默認(rèn)用于 POCO,除非你明確的知道你需要一個 shared_ptr
可以移入新的所有者,但不能拷貝或者共享
替代 auto_ptr,auto_ptr 已作廢
對比 boost::scoped_ptr,unique_ptr 更加小巧和高效
長度為一個指針的大小,并且支持右值引用來快速執(zhí)行 C++ 標(biāo)準(zhǔn)庫容器的插入和遍歷操作
shared_ptr
引用計數(shù)智能指針
當(dāng)你需要將原始指針分派給多個所有者時使用,例如,當(dāng)你從容器返回一個指針的拷貝并且想要保留它
原始指針不會被 delete 直到所有的 shared_ptr 超出作用域或者放棄所有權(quán)。
長度為兩個指針的大小,一個用于對象,另一個用于包含引用計數(shù)的共享控制塊
weak_ptr
結(jié)合 shared_ptr 使用的特殊智能指針。
weak_ptr 提供了對被一個或者多個 shared_ptr 所擁有的對象的訪問,但不參與引用計數(shù)。
如果你想要監(jiān)測某個對象,不要求其不被釋放,可以使用 weak_ptr
在某些情況下,用于解決 shared_ptr 實(shí)例間的循環(huán)引用。
關(guān)于如何使用c++ 智能指針就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。