c++11之智能指針
使用c++,除了c++的語法外,指針是我們麵臨的最的大一個問題,由於使用不當就會導致程序意外退出,或著內存的占用越來越多,總結起來這些錯誤由以下三個原因造成。
1 野指針:指針指向的內存已經被釋放,但是我們還在使用該指針,或者還在使用之前指向的指針,此時程序會崩潰,也有可能導致已經釋放的內存被重新分配給程序使用,造成意想不到的後果。
2 重複釋放:程序嚐試釋放已經被釋放的內存單元,或者釋放已經被重新分配過的內存單元,會導致重複釋放錯誤。
3 內存泄漏:不需要的內存單元沒有釋放,一旦程序一直在重複這樣的操作,會導致程序的內存占用月來越高。
雖然顯示的手動管理內存,給程序的內存管理帶來了很大的自由度,可以高效的利用係統的內存,但是也是非常容易出錯的,隨著多線程程序的出現和廣泛使用,這樣的問題會更加嚴重,因此c++11通過智能指針來擺脫顯示的內存管理,標準庫還實現了‘最小垃圾回收’的支持。
如果你想學習C/C++可以來這個群,首先是三三零,中間是八五九,最後是七六六,裏麵有大量的學習資料可以下載。
c++11中通過unique_ptr,shared_ptr和weak_ptr等智能指針來實現自動釋放堆內存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
#include <memory>
#include <iostream>
using namespace std;
struct Test{
int a;
};
class Demo {
public:
Demo() {
b = new Test();
std::cout << "Demo ()" << std::endl;
}
~Demo() {
std::cout << "~Demo ()" << std::endl;
}
void Say() {
std::cout << "Dem::Say()==>" << b->a << std::endl;
}
public:
Test *b;
};
int main()
{
std::cout << "////////////////unique_ptr///////////////////////" << std::endl;
////////////////unique_ptr///////////////////////
unique_ptr<Demo> unique_ptr_demo1(new Demo);
unique_ptr_demo1->Say();
// unique_ptr<Demo> unique_ptr_demo2 = unique_ptr_demo1; //無法通過編譯
Demo demo2 = *unique_ptr_demo1;
unique_ptr<Demo> unique_ptr_demo3 = move(unique_ptr_demo1);
unique_ptr_demo3->Say();
// Demo demo5 = *unique_ptr_demo1; //運行時錯誤
//
////////////////shared_ptr///////////////////////
std::cout << "////////////////shared_ptr///////////////////////" << std::endl;
shared_ptr<Demo> shared_ptr_demo1(new Demo());
shared_ptr_demo1->Say();
// shared_ptr_demo1.reset();
shared_ptr<Demo> shared_ptr_demo2 = shared_ptr_demo1;
shared_ptr_demo1.reset();
// shared_ptr_demo2.reset(); //運行時錯誤2
shared_ptr_demo2->Say();
return 0;
}
這裏我們可以看到不用我們手動釋放指針指向的內存,編譯器會幫我們釋放該內存,對於析構函數的三次調用,分別對應unique_ptr_demo3,demo2和shared_ptr_demo1. 我們主要看unique_ptr和shared_ptr的區別,unique_ptr跟所指對象的內存緊緊的綁定在一起,不和其他的指針共享其指向的內存(例子中:無法通過編譯的注釋),也就是說unique_ptr不能賦值給別的unique_ptr,更深的講,實際上unique_ptr的拷貝構造函數被刪除,所以我們不能賦值。但是我們可以通過move語義來竊取unique_ptr的內存,但是要注意注釋:運行時錯誤,我們竊取了內存後,該指針就不能在使用了,因為他指向的內存已經被偷走了,特別是當它的成員變量中有指針時,會造成程序崩潰。 shared_ptr可以賦值,允許多個shared_ptr共享一塊內存,它采用了引用計數的內存管理方式,因此當它放棄了所有權時並不會釋放內存,不回影響其他引用這塊內存的指針,隻有當引用計數變為0時才會釋放內存。我們可以看到例子中 shared_ptr_demo1.reset();並沒有影響shared_ptr_demo2(注:shared_ptr_demo1.reset的注釋此處會徹底釋放內存,shared_ptr_demo2會成為一個空指針)所以當我們通過reset顯示的來銷毀指針時,當引用計數沒有為0時隻是把指針設置成nullptr而已。因此既然編輯器會幫我們管理內存,如果不是特殊需求,就不要去顯示的調用reset函數來釋放銷毀指針。
|
最後更新:2017-04-17 16:00:45