日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

标准库中的智能指针shared_ptr

發布時間:2025/4/16 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 标准库中的智能指针shared_ptr 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  智能指針的出現是為了能夠更加方便的解決動態內存的管理問題。注:曾經記得有本書上說可以通過vector來實現動態分配的內存的自動管理,但是經過試驗,在gcc4.8.5下是不行的。這個是容易理解的,vector是個模板,它不能辨別傳入的數據類型是否是指針,從而也不能進行自動的釋放內存操作。如果對非new出的對象進行delete操作,反而還會引起一些不必要的問題。

  C++11標準庫為了能夠使程序員能夠更安全的使用動態內存,提供了兩種智能指針類型來管理動態對象。

shared_ptr類

  智能指針也是模板,所以當我們創建一個智能指針時也需要提供額外的信息——指針可以指向的類型。例如:

  shared_ptr<string> sp1;  //sp1是這個智能指針的名字,尖括號里的string表示這個智能指針指向的是一個string類型的變量(記住,雖然這里沒有我們熟悉的? * ,但sp1是一個指針),默認初始化的智能指針中保存者一個空指針。

  智能指針的使用和普通指針一致,解引用一個指針返回它所指向的對象,如果在一個條件判斷中使用智能指針效果就是檢測它是否為空。

shared_ptr<string> sp1; if(sp1) {std::cout << "判斷智能指針sp1是否為空指針" << std::endl; } if(sp1!= nullptr ) {if(sp1->empty()){
     *sp1 = "Hi Smart Pointer!";    //給該智能指針指向的字符串賦值std::cout
<< "判斷該智能指針指向的字符串是否為空!" << std::endl;} }

  shared_ptr和unique_ptr都支持的操作:

shared_ptr<T> sp / unique_ptr<T> up聲明一個智能指針,默認初始化時,該智能指針中保存著一個空指針
p 將p作為一個條件判斷,若p指向一個對象,則為true(和普通指針一樣,就是判斷指針本身是否為nullptr)
*p解引用p,獲得它指向的對象。和普通指針的*p語義一樣。
p->mem等價于(*p).mem
p.get()返回p中保存的指針,但是這個方法使用起來要小心,如果智能指針釋放了其對象,返回的指針所指向的對象也就消失了
swap(p.q)交換p和q中的指針
p.swap(q)和swap(p.q)的作用是一樣的

  shared_ptr獨有的操作

make_shared<T>(args)args:這種表達在C++primer里就是參數列表的意思。make_shared<T>(args)返回一個shared_ptr指針,指向一個動態分配的類型為T的對象,使用args來初始化此對象(相當于是給構造函數傳參)
shared_ptr<T>p(q)p是shared_ptr q的拷貝,此操作會遞增q中的引用計數器。q中的指針必須要能轉換成T*
p = qp和q都是shared_ptr,所保存的指針必須能夠相互轉換,此操作會遞減p的引用計數,遞增q的引用計數;若p的一用計數變為0,則將其管理的原內存釋放
p.unique() 若p.use_count()為1則返回true;否則返回false
p.use_count()返回與p共享對象的智能指針的數量;可能很慢,主要用于調試。

  shared_ptr和unique_ptr的區別:shared_ptr允許多個指針指向同一個對象,unique_ptr則“獨占”所指向的對象。weak_ptr是一種伴隨類,是一種弱引用,指向shared_ptr所管理的對象。這三種類型都定義在頭文件memory中。

  示例:

#include <iostream> #include <string> #include <memory>using namespace std; int main(int argc,char *argv[]) {shared_ptr<int> sp1;if(nullptr == sp1){std::cout << "shared_ptr默認初始化時,其內保存著一個空指針" << std::endl;}if(sp1.use_count() == 0){std::cout << "默認初始化時,這個智能指針的引用計數值是:" << sp1.use_count() << std::endl;}shared_ptr<int> sp2 = make_shared<int>(42); //聲明一個指向int類型的智能指針,并將其初始化為42,sp2這個智能指針的引用計數值應該是1std::cout << "這個智能指針內保存的值是:" << *sp2 << ",它的引用計數器的值是:" << sp2.use_count() << std::endl;sp1 = sp2; //無論何時,拷貝一個shared_ptr,它的引用計數器都會遞增,例如將用一個shared_ptr初始化另外一個shared_ptr,或者將它作為參數傳遞給一個函數,以及作為函數的返回值//當我們給shared_ptr賦予了一個新值或者是shared_ptr被銷毀,它所關聯的引用計數器就會遞減,一旦一個shared_ptr的計數器變為0,它就會自動釋放自己所管理的對象.std::cout << "sp1的引用計數值是:" << sp1.use_count() << ",sp2的引用計數值是:" << sp2.use_count() << std::endl;shared_ptr<int> sp3 = make_shared<int>(32);sp2 = sp3; //給sp2賦予一個新的值,這里sp2里關聯到原來指向的那個對象的引用計數器值會遞減,但同時,它又被指向了新的對象,這個關聯到新對象的引用計數值又會增加。std::cout << "sp2關聯的計數器值是:" << sp2.use_count() << ",sp3關聯的引用計數器值是:" << sp3.use_count() << "sp1關聯的應用計數器值是:" << sp1.use_count() << std::endl;//當指向一個對象的最后一個shared_ptr被銷毀時,shared_ptr類會自動銷毀此對象,通過析構函數完成此工作。shared_ptr的析構函數會遞減它所指向的對象的引用計數。如果引用計數變為0,則shared_ptr//的析構函數就會銷毀對象,并釋放它占用的內存, {shared_ptr<int> sp4 = make_shared<int>(3);sp1 = sp4;}if(sp1!= nullptr){std::cout << "上面的sp4雖然被銷毀了,但是由于有sp1=sp4這個賦值操作,導致指向sp4原本指向的對象的指針對于0個,那么它申請的內存就不會隨著sp4的析構而銷毀。" << "sp1當前所保存的值是: " << *sp1 << std::endl;}//shared_ptr在無用之后仍然保留的一種情況是,你將shared_ptr存放在一個容器中,隨后重排了容器,從而不再需要某些元素,在這種情況下,你應該確保erase刪除那些不需要的shared_ptr元素。return (0); }

  分配動態內存的幾個理由:

  1.不知道自己想要多大的空間;

  2.不知道對象的類型是什么,(void *)

  3.需要多個對象共享數據

  程序非自由空間被耗盡的情況還是有可能發生的,一旦一個程序用光了它所有可用的內存,new表達式就會失敗。默認情況下,如果new不能分配所要求的的內存空間,它會拋出一個類型為bad_alloc的異常。可以改變使用new的方式來阻止它拋出異常。

int *p2 = new (nothrow) int; //此時如果分配內存失敗,那么new就會返回一個空指針,這種形式的new稱為定位new,定位new表達式允許我們向new傳遞額外參數。這個例子中傳入的是一個由標準庫定義的名為nothrow的對象,意思就是不拋出異常。這個都定義在頭文件new中

  new運算符包含兩個動作:分配內存,構造對象。

  delete運算符負責釋放new運算符分配的內存,把它還給操作系統,delete也包含兩個動作,銷毀給定的指針指向的對象,釋放對應的內存。

  傳給delete的指針必須是動態分配的內存或者是一個空指針,釋放一塊并非new分配的內存,或者將相同的指針釋放多次,其行為是未定義的。

  動態對象的生存期直到被釋放時為止。(new/delete? new出來的指針被稱為內置指針)

動態內存的管理里容易出現的幾個問題:

1.忘記delete內存。忘記釋放動態內存常會導致“內存泄漏”問題,因為這種內存永遠不可能歸還給自由空間了。

2.使用已經釋放掉的對象。通過在釋放內存后將指針置為空,有時可以檢測出這種錯誤。如果不置為空,那么會產生空懸指針(野指針)。這會造成災難性的后果。

3.同一塊內存釋放兩次,當有兩個指針指向相同的動態分配對象時,可能發生這種錯誤。如果對其中一個指針進行了delete操作,對象的內存就被歸還給自由空間了,如果隨后又對第二個指針進行delete操作,自由空間就可能被破壞。

shared_ptr和new的結合使用

  主要用于shared_ptr的初始化。使用示例如下:

shared_ptr<int> sp1 = new int(0); //這是錯誤的 shared_ptr<int> sp2(new int(0)); //這才是正確的寫法

  默認情況下,一個用來初始化智能指針的普通指針必須要指向動態內存,因為智能指針默認使用delete來釋放它所關聯的對象。

shared_ptr<T> p(q)p管理內置指針q所指向的對象,q必須指向new分配的內存,且能夠轉換為T*
shared_ptr<T> p(u)p從unqiue_ptr u那里接管了對象的所有權。將u置為空
shared_ptr<T> p(q,d)p接管了內置指針q所指向的對象得到所有權。q必須能夠轉換為T*類型,p將使用可調用對象d來代替delete
shared_ptr<T> p(p2,d)p是shared_ptr p2的額拷貝,唯一的區別是,p將可調用對象d來代替delete
p.reset()若p是唯一指向其對象的shared_ptr,reset會釋放此對象。
p.reset(q)若傳遞了可選的參數內置指針q,會令p指向q,否則會將p置為空
p.reset(q,d)傳遞了內置指針q和可調用對象d,那么會使用d來替代delete

  不要使用get初始化另外一個智能指針或為智能指針賦值,get是用來給那些只能使用內置指針的地方來用的。

  在使用reset之前,我們要檢查自己是不是當前對象僅有的用戶,如果不是,那么在使用之前要制作一份新的拷貝。函數退出的兩種情況:正常退出和發生異常。無論哪種情況,局部對象都會被銷毀。

智能指針使用規范:

  • 不使用相同的內置指針值初始化或reset多個智能指針
  • 不delete get返回的指針
  • 不使用get()初始化或reset另一個智能指針
  • 如果你使用了get()返回的指針,記住當最后一個對應的智能指針銷毀后,你的指針就無效了
  • 如果你使用智能指針管理的資源不是new分配內存,記住傳遞給它一個刪除器。

轉載于:https://www.cnblogs.com/ToBeExpert/p/10045948.html

總結

以上是生活随笔為你收集整理的标准库中的智能指针shared_ptr的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。