日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 單片機(jī) > 程序喵大人

最近,有同學(xué)來(lái)問(wèn)我,想了解C++的三種智能指針的使用場(chǎng)景,在項(xiàng)目中應(yīng)該如何選擇?

首先要了解這三種智能指針的特點(diǎn),std::unique_ptrstd::shared_ptrstd::weak_ptr

std::unique_ptr

std::unique_ptr是一種獨(dú)占所有權(quán)的智能指針,意味著同一時(shí)間內(nèi)只能有一個(gè)unique_ptr指向一個(gè)特定的對(duì)象。

當(dāng)unique_ptr被銷毀時(shí),它所指向的對(duì)象也會(huì)被銷毀。

使用場(chǎng)景:

  • 當(dāng)你需要確保一個(gè)對(duì)象只被一個(gè)指針?biāo)鶕碛袝r(shí)。
  • 當(dāng)你需要自動(dòng)管理資源,如文件句柄或互斥鎖時(shí)。
  • 當(dāng)你不確定用哪種智能指針時(shí),優(yōu)先選擇unique_ptr就沒(méi)毛病。

示例代碼:

#include  #include   class Test { public: Test() { std::cout << "Test::Test()\n"; } ~Test() { std::cout << "Test::~Test()\n"; } void test() { std::cout << "Test::test()\n"; } };  int main() {  std::unique_ptr  ptr(new Test());  ptr->test();  // 當(dāng)ptr離開(kāi)作用域時(shí),它指向的對(duì)象會(huì)被自動(dòng)銷毀  return0; } 

std::shared_ptr

std::shared_ptr是一種共享所有權(quán)的智能指針,多個(gè)shared_ptr可以指向同一個(gè)對(duì)象。內(nèi)部使用引用計(jì)數(shù)來(lái)確保只有當(dāng)最后一個(gè)指向?qū)ο蟮?/span>shared_ptr被銷毀時(shí),對(duì)象才會(huì)被銷毀。

使用場(chǎng)景:

  • 當(dāng)你需要在多個(gè)所有者之間共享對(duì)象時(shí)。
  • 當(dāng)你需要通過(guò)復(fù)制構(gòu)造函數(shù)或賦值操作符來(lái)復(fù)制智能指針時(shí)。

示例代碼:

#include  #include   class Test { public: Test() { std::cout << "Test::Test()\n"; } ~Test() { std::cout << "Test::~Test()\n"; }void test() { std::cout << "Test::test()\n"; } };  int main() {  std::shared_ptrptr1(new Test());  std::shared_ptrptr2 = ptr1;  ptr1->test();  // 當(dāng)ptr1和ptr2離開(kāi)作用域時(shí),它們指向的對(duì)象會(huì)被自動(dòng)銷毀  return0; } 

std::weak_ptr

std::weak_ptr是一種不擁有對(duì)象所有權(quán)的智能指針,它指向一個(gè)由std::shared_ptr管理的對(duì)象。weak_ptr用于解決shared_ptr之間的循環(huán)引用問(wèn)題。

是另外一種智能指針,它是對(duì) shared_ptr 的補(bǔ)充,std::weak_ptr 是一種弱引用智能指針,用于觀察 std::shared_ptr 指向的對(duì)象,而不影響引用計(jì)數(shù)。它主要用于解決循環(huán)引用問(wèn)題,從而避免內(nèi)存泄漏,另外如果需要追蹤指向某個(gè)對(duì)象的第一個(gè)指針,則可以使用 weak_ptr。

可以考慮在對(duì)象本身中維護(hù)一個(gè)指向第一個(gè) shared_ptr 的弱引用(std::weak_ptr)。當(dāng)創(chuàng)建對(duì)象的第一個(gè) shared_ptr 時(shí),將這個(gè) shared_ptr 賦值給對(duì)象的 weak_ptr 成員。這樣,在需要時(shí),可以通過(guò)檢查對(duì)象的 weak_ptr 成員來(lái)獲取指向?qū)ο蟮牡谝粋€(gè) shared_ptr(如果仍然存在的話).

使用場(chǎng)景:

  • 當(dāng)你需要訪問(wèn)但不擁有由shared_ptr管理的對(duì)象時(shí)。
  • 當(dāng)你需要解決shared_ptr之間的循環(huán)引用問(wèn)題時(shí)。
  • 注意weak_ptr肯定要和shared_ptr搭配使用。

示例代碼:

#include  #include   class Test { public: Test() { std::cout << "Test::Test()\n"; } ~Test() { std::cout << "Test::~Test()\n"; }void test() { std::cout << "Test::test()\n"; } };  int main() {  std::shared_ptrsharedPtr(new Test());  std::weak_ptrweakPtr = sharedPtr;   if (auto lockedSharedPtr = weakPtr.lock()) {  lockedSharedPtr->test();  }// 當(dāng)sharedPtr離開(kāi)作用域時(shí),它指向的對(duì)象會(huì)被自動(dòng)銷毀  return0; } 

這三種智能指針各有其用途,選擇哪一種取決于你的具體需求。

1)智能指針?lè)矫娴慕ㄗh:

  • 盡量使用智能指針,而非裸指針來(lái)管理內(nèi)存,很多時(shí)候利用RAII機(jī)制管理內(nèi)存肯定更靠譜安全的多。
  • 如果沒(méi)有多個(gè)所有者共享對(duì)象的需求,建議優(yōu)先使用unique_ptr管理內(nèi)存,它相對(duì)shared_ptr會(huì)更輕量一些。
  • 在使用shared_ptr時(shí),一定要注意是否有循環(huán)引用的問(wèn)題,因?yàn)檫@會(huì)導(dǎo)致內(nèi)存泄漏。
  • shared_ptr的引用計(jì)數(shù)是安全的,但是里面的對(duì)象不是線程安全的,這點(diǎn)要區(qū)別開(kāi)。

2)為什么std::unique_ptr可以做到不可復(fù)制,只可移動(dòng)?

因?yàn)榘芽截悩?gòu)造函數(shù)和賦值運(yùn)算符標(biāo)記為了delete,見(jiàn)源碼:

template <typename _Tp, typename _Tp_Deleter = default_delete>  class unique_ptr { // Disable copy from lvalue. unique_ptr(const unique_ptr&) = delete;  template<typename _Up, typename _Up_Deleter>  unique_ptr(const unique_ptr<_Up, _Up_Deleter>&) = delete;  unique_ptr& operator=(const unique_ptr&) = delete;  template<typename _Up, typename _Up_Deleter>  unique_ptr& operator=(const unique_ptr<_Up, _Up_Deleter>&) = delete; }; 

3)shared_ptr的原理:

每個(gè) std::shared_ptr 對(duì)象包含兩個(gè)成員變量:一個(gè)指向被管理對(duì)象的原始指針,一個(gè)指向引用計(jì)數(shù)塊的指針(control block pointer)。

引用計(jì)數(shù)塊是一個(gè)單獨(dú)的內(nèi)存塊,引用計(jì)數(shù)塊允許多個(gè) std::shared_ptr 對(duì)象共享相同的引用計(jì)數(shù),從而實(shí)現(xiàn)共享所有權(quán)。

當(dāng)創(chuàng)建一個(gè)新的 std::shared_ptr 時(shí),引用計(jì)數(shù)初始化為 1,表示對(duì)象當(dāng)前被一個(gè) shared_ptr 管理。

  1. 拷貝 std::shared_ptr:當(dāng)用一個(gè) shared_ptr 拷貝出另一個(gè) shared_ptr 時(shí),需要拷貝兩個(gè)成員變量(被管理對(duì)象的原始指針和引用計(jì)數(shù)塊的指針),并同時(shí)將引用計(jì)數(shù)值加 1。這樣,多個(gè) shared_ptr 對(duì)象可以共享相同的引用計(jì)數(shù)。
  2. 析構(gòu) std::shared_ptr:當(dāng) shared_ptr 對(duì)象析構(gòu)時(shí),引用計(jì)數(shù)值減 1。然后檢測(cè)引用計(jì)數(shù)是否為 0。如果引用計(jì)數(shù)為 0,說(shuō)明沒(méi)有其他 shared_ptr 對(duì)象指向該資源,因此需要同時(shí)刪除原始對(duì)象(通過(guò)調(diào)用自定義刪除器,如果有的話)。

4)智能指針的缺點(diǎn)

  1. 性能開(kāi)銷,需要額外的內(nèi)存來(lái)存儲(chǔ)他們的控制塊,控制塊包括引用計(jì)數(shù),以及運(yùn)行時(shí)的原子操作來(lái)增加或減少引用技術(shù),這可能導(dǎo)致裸指針的性能下降。
  2. 循環(huán)引用問(wèn)題,如果兩個(gè)對(duì)象通過(guò)成員變量shared_ptr相互引用,并且沒(méi)有其他指針指向這兩個(gè)對(duì)象中的任何一個(gè),那么這兩個(gè)對(duì)象的內(nèi)存將永遠(yuǎn)不會(huì)被釋放,導(dǎo)致內(nèi)存泄露。
#include #include class B;// 前向聲明  class A { public: std::shared_ptr b_ptr; ~A() {  std::cout << "A has been destroyed."<< std::endl; } };  class B { public: std::shared_ptr a_ptr; ~B() {  std::cout << "B has been destroyed."<< std::endl; } };  int main() {  std::shared_ptr a = std::make_shared();  std::shared_ptr b = std::make_shared();  a->b_ptr = b; // A 引用 B  b->a_ptr = a; // B 引用 A  // 由于存在循環(huán)引用,A 和 B 的析構(gòu)函數(shù)將不會(huì)被調(diào)用,從而導(dǎo)致內(nèi)存泄漏  return0; } 
  1. 智能指針不一定適用于所有場(chǎng)景:有一些容器類,內(nèi)部實(shí)現(xiàn)依賴于裸指針,另外在考慮某些性能關(guān)鍵場(chǎng)景下,使用裸指針可能更合適。但絕大多數(shù)場(chǎng)景,用智能指針就OK。

選型建議

  1. 默認(rèn)選擇unique_ptr,因?yàn)樗阅茏顑?yōu),且語(yǔ)義清晰,比如局部動(dòng)態(tài)對(duì)象。
  2. 當(dāng)你發(fā)現(xiàn)unique_ptr使用受限,那大概率就是有需要共享的需求,需要多個(gè)模塊或?qū)ο笮韫蚕硗毁Y源時(shí)(如全局配置、線程間共享數(shù)據(jù)),使用shared_ptr,但要注意循環(huán)引用的問(wèn)題。
  3. 優(yōu)先使用make_uniquemake_shared構(gòu)造對(duì)應(yīng)的智能指針,具備異常安全性。
  4. 避免裸指針和智能指針混用,容易出現(xiàn)double free等問(wèn)題。
  5. unique_ptr放心使用,并沒(méi)有額外開(kāi)銷。
  6. shared_ptr 的引用計(jì)數(shù)可能引發(fā)原子操作開(kāi)銷,除非對(duì)性能有非常極致的要求,否則沒(méi)必要在意這點(diǎn)開(kāi)銷。也要注意循環(huán)引用會(huì)導(dǎo)致內(nèi)存泄漏。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉