shared_ptr和new结合使用的几个简单例子
process的定義如下:?
void process(shared_ptr<int> ptr) {cout << "shared_ptr is:" << *ptr << endl; }1.接受指針參數的智能指針是explicit的,我們不能將一個內置指針轉換為智能指針,必須使用直接初始化形式,如下:
shared_ptr<int> p(new int(1234));但是不能寫成下面形式:
shared_ptr<int> p = new int(1234);因為不能從內置指針轉化為智能指針。
2. 一個用來初始化智能指針的普通指針必須指向動態內存,因為智能指針默認使用delete來釋放它所關聯的對象。我們可以將智能指針綁定到指向其它類型的資源的指針上,但是為了這樣做,必須提供自己的操作來代替delete。
?
3.智能指針改變shared_ptr的其它方法。
?4.不要混合使用內置指針和智能指針
shared_ptr<int> p(new int(1024)); process(p); int number = *p; //正確,p的引用計數值為1 int *x = new int(1234); //下面語句process是參數ptr會接受臨時構造的智能指針,但是ptr的引用計數是1,運行完畢后會釋放內存 process(shared_ptr<int>(x));//process接受的臨時構造的一個對象,運行完畢后釋放這個對象int *y = x;//這個x指向的內存已經被釋放了,所以這個語句是未定義的process運行后,x指向的內存會被釋放,但是x會繼續指向原來的內存,但是內存已經被釋放。如果再繼續試圖使用x的值,那么結果是未定義的。
當我們將一個內置指針綁定到shared_ptr時,我們就將內置指針的管理責任交給了這個shared_ptr了,一旦這樣做了,我們就不該再使用內置指針來訪問shared_ptr所指向的內存了。
5.也不要使用get初始化另一個智能指針或為智能指針賦值。
(1)get返回的指針不能delete,隨便可以編譯通過,但是g++編譯器會產生運行時候錯誤:
free(): double free detected in tcache 2 lAborted (core dumped)因為如果get返回的指針被delete,那么原來智能指針在程序結束時候也會銷毀操作,那么此時統一塊內存就被釋放2次,所以會發生double free detected(檢測到兩次內存釋放)
(2)不能用get返回的指針初始化另一個智能指針(雖然可以編譯通過),否則還會出現運行時錯誤(g++編譯器):
free(): double free detected in tcache 2 lAborted (core dumped)例1:
shared_ptr<int> p(new int(1024)); int *q = p.get(); shared_ptr<int> w = shared_ptr<int>(q);原因如下,程序結束的時候,p和w將先后被銷毀,但是由于p和w指向相同的內存,又是2個完全不同的智能指針(各自引用計數都是1),所以當執行后一個智能指針銷毀操作時候就會出現double free detected,同樣的內存釋放2此。本例根源在于用一個相同內存構造了2個引用計數都是1 的智能指針,結果出現錯誤。因此,c++ primer 5th,414頁上有下面一句話:
只要用get返回的智能指針初始化另一個智能指針,就會出現double free detected的運行時的錯誤。以上例1就是一個例子。代碼段 小部件
下面再看看用get返回的智能指針給另一個智能指針賦值會出現什么問題,如下:
shared_ptr<int> p(new int(1024)); int *q = p.get(); shared_ptr<int> p2 = shared_ptr<int>(q);g++編譯器會提示下面錯誤:
free(): double free detected in tcache 2 Aborted (core dumped)道理一樣,還是因為兩個智能指針指向同一個內存,而兩個智能指針的各自引用計數是1,所以兩個都銷毀的時候,就會發生double free detected錯誤。當然,也不能用一個內置指針構造兩個智能指針,否則會發生和get返回值構造智能指針或者給智能指針賦值同樣的問題:
int *ptr = new int(1234); shared_ptr<int> p1(ptr); shared_ptr<int> p2(ptr);6.可以用一個指針構造一個臨時的智能指針,但是要注意以下準則
(1)一定不能用get返回值構造一個智能指針
? (2)可以利用一個智能指針構造一個智能指針然后間接初始化或者給另一個智能指針賦值,引用計數加1
? ?(3)謹慎用一個內置指針構造一個智能指針,因為被賦值的智能指針離開作用域后會被銷毀,指針所指內存會被釋放。內置指針也不能用了。所以一旦把一個內置指針交給智能指針管理,就不要再用內置指針訪問它所指向的內存了。
例如:
int *ptr = new int(1234); shared_ptr<int> p1(ptr);7.如果我們如下面調用process,會發生什么?
process(shared_ptr<int>(p.get()));答:會發生double free detected...的錯誤;利用p.get()返回值構造一個臨時的shared_ptr,那么process的參數ptr接受了這個實參后,會指向p.get()指向的內存,但是因為是利用p.get()構造的,將不會形成正確的動態對象共享。編譯器會認為p和ptr是使用兩個地址(雖然它們相等)創建的兩個不相干的shared_ptr,而非共享一個動態共享。兩者的引用計數都是1.當process執行完畢后,ptr的引用計數變為0,所管理的內存地址被釋放,而此內存是p管理的,p稱為一個空懸指針的shared_ptr,最后程序結束的時候釋放p的時候會引發二次釋放內存,即double free detected......
8.c++primer 5th的一個習題,如下:
下面的語句是否合法,如果合法,它做了什么?
process(new int());答案說的是合法,但是其實是不合法的,實參到形參是一種轉換,但是new int()不能轉化為shared_ptr,所以不合法。也就是不能從內置指針轉化為shared_ptr。
9.下面的語句是否合法,為什么?
int *ptr = new int(1234); process(shared_ptr<int>(ptr));答:當process執行完畢后,ptr指向的內存會被釋放。
這個用法可以說是錯誤的。因為把內置指針ptr破壞了。
10.不要delete通過get返回的指針,否則引發錯誤double free detected...
auto sp = make_shared<int>();auto p = sp.get();delete p;不用想,肯定會發生double free detected的錯誤。
以下是幾個自己推測的結論:
get返回的指針和new得到的指針是一個類型的,都可以delete,所以都是動態內存。如果get()后的指針被delete,那么會提現釋放智能指針的內存,等到智能指針在程序結束的時候釋放的時候,發現內存已經被釋放,從而會發生double free detected.....
11.智能指針和異常
?
總結
以上是生活随笔為你收集整理的shared_ptr和new结合使用的几个简单例子的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 动态分配的const对象
- 下一篇: allocator类初学的简单例子