欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c++ 智能指針基礎詳解

 更新時間:2021年02月18日 17:03:43   作者:Er_HU  
這篇文章主要介紹了c++ 智能指針基礎的相關資料,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下

簡介

在現(xiàn)代 C++ 編程中,標準庫包含了智能指針(Smart pointers)。

智能指針用來確保程序不會出現(xiàn)內存和資源的泄漏,并且是"異常安全"(exception-safe)的。

智能指針的使用

智能指針定義在頭文件 memory 里的命名空間 std 中。它對于資源獲取即初始化(RAII, Resource Acquisition Is Initialization) 編程理念至關重要。該理念的目的是保證對象初始化的時候也是資源獲取的時候,從而使對象的所有資源在單行代碼中創(chuàng)建。

實踐中,RAII 的主要原則就是把任何在堆上分配的資源(比如動態(tài)分配的內存或者系統(tǒng)對象的處理)的所有權提供給在棧上分配的對象(其析構函數(shù)包含釋放資源及相關清理的代碼)。

大多數(shù)時候,當你初始化一個原始指針或者資源句柄使其指向實際的資源時,立即將其傳給智能指針。

在現(xiàn)代 C++ 中,原始指針只用于包含在局部作用域,循環(huán)或者工具函數(shù)的小塊代碼中(對性能有要求,并且對資源的所有權也不容易混淆)。

原始指針和智能指針的聲明比較如下:

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_ptr<Song> song2(new Song(L"Nothing on You", L"Bruno Mars"));

 // Use song2...
 wstring s = song2->duration_;
 //...

} // song2 is deleted automatically here.

如上所示,智能指針是一個在棧上聲明的類模板,并由指向分配在堆上的對象的原始指針初始化。當智能指針初始化后,它就擁有了原始指針的所有權。這意味著智能指針需要負責原始指針指向的內存釋放。智能指針的析構函數(shù)包含了 delete 的調用,并且由于智能指針是在棧上聲明的,其析構函數(shù)會在智能指針對象離開作用域時被調用,即使在棧中發(fā)生了異常。

通過使用指針運算符(-> 和 *)訪問被封裝的指針,智能指針類重載了這些運算符以返回被封裝的原始指針。

C++ 智能指針的理念類似于在 C# 語言中創(chuàng)建對象的過程:創(chuàng)建對象后讓系統(tǒng)負責在正確的時間將其刪除。不同之處在于,沒有獨立的垃圾回收器運行于后臺;內存是按照標準 C++ 規(guī)范對內存進行管理的,使運行時環(huán)境更加快速和高效。

[!重要]

總是在單獨的行上創(chuàng)建智能指針,而不是在參數(shù)列表中,從而避免由于特定的參數(shù)列表分配規(guī)則出現(xiàn)一些輕微的內存泄漏

以下示例顯示了 C++ 標準庫中的 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_ptr<LargeObject> pLarge(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.

上述示例演示了使用智能指針的關鍵步驟:

  1. 將智能指針聲明為局部變量(不要在智能指針上使用 new 或者 malloc 表達式)。
  2. 在類型參數(shù)上,指定被封裝指針指向的對象類型。
  3. 將指向由 new 創(chuàng)建的對象的指針傳給智能指針的構造函數(shù)。
  4. 使用重載的操作符 -> 和 * 來訪問對象。
  5. 讓智能指針來 delete 對象。

智能指針在設計上兼顧了內存和性能的高效性。例如,unique_ptr 唯一的數(shù)據成員是被封裝的原始指針,這意味著 unique_ptr 具有原始指針同樣地大小,4 字節(jié)或者 8 字節(jié)。通過智能指針重載的操作符 -> 和 * 來訪問并不比直接使用原始指針來訪問慢多少。

智能指針有其自己的成員函數(shù),通過 . 來訪問。例如,一些 C++ 標準庫的智能指針有用于重置的成員函數(shù)來釋放對原始指針的所有權。這可以用于在智能指針超出作用域前釋放智能指針管理的內存,看下面的示例:

void SmartPointerDemo2()
{
 // Create the object and pass it to a smart pointer
 std::unique_ptr<LargeObject> pLarge(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++ 標準庫中的智能指針包含了成員函數(shù) get 來獲取原始指針。 CComPtr 有公共的類成員 p。通過獲取原始指針,你能夠使用智能指針來管理你自己代碼涉及的內存并依然能夠將原始指針傳遞給不支持智能指針的代碼。

void SmartPointerDemo4()
{
 // Create the object and pass it to a smart pointer
 std::unique_ptr<LargeObject> pLarge(new LargeObject());

 //Call a method on the object
 pLarge->DoSomething();

 // Pass raw pointer to a legacy API
 LegacyLargeObjectFunction(pLarge.get()); 
}

智能指針的種類

以下部分總結了在 Windows 環(huán)境下不同種類的智能指針,以及如何使用它們。

C++ 標準庫中的智能指針

優(yōu)先使用下列智能指針來封裝原始指針指向的純舊對象(plain old C++ objects,POCO):

unique_ptr

  • 對封裝的原始指針是獨占的
  • 默認用于 POCO,除非你明確的知道你需要一個 shared_ptr
  • 可以移入新的所有者,但不能拷貝或者共享
  • 替代 auto_ptr,auto_ptr 已作廢
  • 對比 boost::scoped_ptr,unique_ptr 更加小巧和高效
  • 長度為一個指針的大小,并且支持右值引用來快速執(zhí)行 C++ 標準庫容器的插入和遍歷操作

shared_ptr

  • 引用計數(shù)智能指針
  • 當你需要將原始指針分派給多個所有者時使用,例如,當你從容器返回一個指針的拷貝并且想要保留它
  • 原始指針不會被 delete 直到所有的 shared_ptr 超出作用域或者放棄所有權。
  • 長度為兩個指針的大小,一個用于對象,另一個用于包含引用計數(shù)的共享控制塊

weak_ptr

  • 結合 shared_ptr 使用的特殊智能指針。
  • weak_ptr 提供了對被一個或者多個 shared_ptr 所擁有的對象的訪問,但不參與引用計數(shù)。
  • 如果你想要監(jiān)測某個對象,不要求其不被釋放,可以使用 weak_ptr
  • 在某些情況下,用于解決 shared_ptr 實例間的循環(huán)引用。

擴展

  • 用于 COM 組件的智能指針
  • 用于 POCO對象的ATL智能指針

引用

Microsoft Docs (https://docs.microsoft.com/en-us/cpp/cpp/smart-pointers-modern-cpp?view=msvc-160)

以上就是c++ 智能指針基礎詳解的詳細內容,更多關于c++ 智能指針的資料請關注腳本之家其它相關文章!

相關文章

  • C語言動態(tài)數(shù)組的使用實現(xiàn)代碼

    C語言動態(tài)數(shù)組的使用實現(xiàn)代碼

    這篇文章主要介紹了C語言動態(tài)數(shù)組的使用實現(xiàn)代碼的相關資料,需要的朋友可以參考下
    2017-01-01
  • 用C語言實現(xiàn)簡單的三子棋

    用C語言實現(xiàn)簡單的三子棋

    這篇文章主要為大家詳細介紹了用C語言實現(xiàn)三子棋,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C++命令行解析包gflags的使用教程

    C++命令行解析包gflags的使用教程

    這篇文章主要給大家介紹了關于C++命令行解析包gflags的使用教程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • 老生常談C/C++內存管理

    老生常談C/C++內存管理

    下面小編就為大家?guī)硪黄仙U凜/C++內存管理。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • C++ 使用CRC32檢測內存映像完整性的實現(xiàn)步驟

    C++ 使用CRC32檢測內存映像完整性的實現(xiàn)步驟

    當我們使用動態(tài)補丁的時候,那么內存中同樣不存在校驗效果,也就無法抵御對方動態(tài)修改機器碼了,為了防止解密者直接對內存打補丁,我們需要在硬盤校驗的基礎上,增加內存校驗,防止動態(tài)補丁的運用。
    2021-06-06
  • c語言結構體字節(jié)對齊的實現(xiàn)方法

    c語言結構體字節(jié)對齊的實現(xiàn)方法

    在c語言的結構體里面一般會按照某種規(guī)則去進行字節(jié)對齊。本文就來介紹一下如何實現(xiàn),具有一定的參考價值,感興趣的可以了解下
    2021-07-07
  • C語言實現(xiàn)輸出鏈表中倒數(shù)第k個節(jié)點

    C語言實現(xiàn)輸出鏈表中倒數(shù)第k個節(jié)點

    這篇文章主要介紹了C語言實現(xiàn)輸出鏈表中倒數(shù)第k個節(jié)點,主要涉及鏈表的遍歷操作,是數(shù)據結構中鏈表的常見操作。需要的朋友可以參考下
    2014-09-09
  • C++有限狀態(tài)機實現(xiàn)計算器小程序

    C++有限狀態(tài)機實現(xiàn)計算器小程序

    這篇文章主要為大家詳細介紹了C++有限狀態(tài)機實現(xiàn)計算器小程序的相關資料,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 基于C語言sprintf函數(shù)的深入理解

    基于C語言sprintf函數(shù)的深入理解

    本篇文章是對C語言中的sprintf函數(shù)進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • AVX2指令集浮點乘法性能分析

    AVX2指令集浮點乘法性能分析

    這篇文章主要為大家介紹了AVX2指令集浮點乘法性能分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05

最新評論