日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Chapter12:动态内存

發布時間:2023/11/27 生活经验 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Chapter12:动态内存 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 智能指針——shared_ptr

為了更容易地使用動態內存,新的標準提供了智能指針來管理動態對象。智能指針的行為類似常規指針,重要的區別是它負責自動釋放指向的對象。

?

智能指針的使用方式與普通指針類似。解引用一個智能指針返回它指向的對象。

1 if (p1 && p1->empty())

?

最安全的分配和使用動態內存的方法是調用一個名為make_shared的標準庫函數

make_shared<T>(args); //返回一個shared_ptr, 指向一個動態分配的類型為T的對象,使用args初始化此對象。

?

shared_ptr自動銷毀所管理的對象,還會自動釋放相關聯的內存。

shared_ptr在無用之后仍然保留的一種可能是:你將shared_ptr存放在一個容器中,隨后重排了容器,從而不在需要某些元素。這個時候你應該確保使用erase刪除那些不再需要的shared_ptr的元素。

?

?

  • 使用了動態生存期的資源的類

(三種情況)

1. 程序不知道自己需要使用多少對象;例如容器類。

2. 程序不知道所需對象的準確類型;例如派生與繼承。

3. 程序需要在多個對象間共享數據;到目前為止,我們使用過的類中,分配的資源都與對應對象生存期一致;但某些類分配的資源具有與原對象相獨立的生存期,即:當某個對象被銷毀時,我們不能單方面地銷毀底層數據。

定義需要共享數據的類時,重點要考慮的是初始化、賦值、拷貝、銷毀等拷貝控制得問題。

?

?

  • 直接管理內存:new/delete

初始化

默認情況下,動態分配的對象時默認初始化的,這意味著內置類型或組合類型的對象的值是未定義的,而類類型對象將用默認構造函數進行初始化;

對于定義了自己的構造函數的類類型來說,要求值初始化沒有意義;不管采用什么形式,對象都會通過默認構造函數來初始化;

1 string *ps1 = new string; //默認初始化為空string
2 string *ps2 = new string(); //默認初始化為空string
3 
4 int* pi1 = new int;//默認初始化;*pi1的值未定義
5 int* pi1 = new int(); //值初始化為0

?

delete

釋放一塊并非new分配的內存,或者將相同的指針值釋放多次,其行為是未定義的。

動態對象的生存期知道被釋放時為止;

delete之后的指針值就變為無效了。雖然指針已經無效,但是很多機器上指針仍然保存著動態內存的地址。此時指針就變為空懸指針(dangling pointer),最好在delete之后將nullptr賦予指針。

動態內存的一個基本問題是:可能多個直著你指向相同的內存,而在實際系統中,查找相同內存的所有指針是異常困難的。

?

?

  • shared_ptr+new

接受指針參數的智能指針構造函數是explicit的,因此我們不能將一個內置指針隱式轉換為一個智能指針,必須使用直接初始化形式。

1 shared_ptr<int> p1 = new int(1024);//錯誤,必須使用直接初始化形式
2 shared_ptr<int> p2(new int(1024));//正確,使用直接初始化形式

不要混合使用普通指針和智能指針——以防止同一塊內存綁定到多個獨立創建的shared_ptr上——推薦使用make_shared,而不是new。

 1 void process(shared_ptr<int> ptr)
 2 {//參數按值傳遞,發生拷貝操作
 3 }
 4 
 5 shared_ptr<int> p(new int(42));
 6 process(p);//在process中引用計數為2
 7 int i = *p;//引用計數為1
 8 
 9 int *x(new int(42));//x是普通指針
10 process(x);//錯誤
11 process(shared_ptr<int>(x));//會釋放x的內存
12 int j = *x;

當將一個shared_ptr綁定到一個普通指針時,我們就將內存管理責任交給了這個shared_ptr。一旦這樣做了,我們就不應該再使用內置指針來訪問shared_ptr所指向的內存了;

使用一個內置指針來訪問一個智能指針所負責的對象時很危險的,因為我們無法知道對象何時會被銷毀。

?

不要使用get初始化另一個智能指針或為智能指針賦值——以防止同一塊內存綁定到多個獨立創建的shared_ptr上。

?

unique():在改變對象之前,我們要檢查自己是否是當前對象的僅有的用戶。如果不是,在改變之前,我們可能需要制作一份新的拷貝。

1 if (!p.unique())
2     p.reset(new string(*p));

?

智能指針使用規范

1. 不使用相同的內置指針值初始化(或reset)多個智能指針;

2. 不 delete get()返回的指針;

3. 不使用get()初始化或reset另一個智能指針;

4. 如果使用了get()返回的指針,記住當最后一個對應的智能指針銷毀后,你的指針就變成無效了;

5. 如果你使用智能指針管理的資源不是new分配的內存,記住傳遞一個刪除器給它。

?

?

  • 動態數組

標準庫提供了一個可以管理new分配的數組的unique_ptr版本。為了用一個unique_ptr管理動態數組,我們必須在對象類型后面加一對空括號:

unique_ptr<int []> up(new int[10]>;
up.release();//自動用delete[]銷毀其指針

與unique_ptr不同,shared_ptr不直接支持管理動態數組。如果希望使用shared_ptr管理動態數組,必須提供自己定義的刪除器:

1 shared_ptr<int> sp(new int[10], [](int *p) {delete[] p; });
2 sp.reset();//使用lambda釋放數組
1 for (size_t i = 0; i != 10; ++i)
2 {
3     up[i] = i;
4     *(sp.get() + i) = i;
5 }

?

?

  • allocator類

new有一些靈活性上的局限,其中一方面表現在它將內存分配和對象構造組合在一起。類似的,delete將對象析構和內存釋放組合在一起;

當分配一大塊內存時,我們通常計劃在這塊內存上按需構造對象。在此情況下,我們希望將內存分配和對象構造分離。這意味著我們可以分配大塊內存,但只在真正需要時才執行對象創建工作。

allocator的兩個伴隨算法:

1 uninitialized_copy(b, e, b2);//從迭代器b和e指定的范圍拷貝元素到迭代器b2指定的未構造的原始內存中。
2 uninitialized_copy_n(b, n, b2)
1 uninitialized_fill(b, e, t);//在迭代器b和e指定的原始內存范圍內創建對象,值均為t的拷貝;
2 uninitialized_fill_n(b, n, t)

?

轉載于:https://www.cnblogs.com/wangyanphp/p/5831109.html

總結

以上是生活随笔為你收集整理的Chapter12:动态内存的全部內容,希望文章能夠幫你解決所遇到的問題。

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