指針是柄雙刃劍,用的好,就會威力倍增;用的稍有閃失,就會造成悲劇。
自從c++11引入智能指針shared_ptr后,我們似乎再也不用擔心new的內存沒有釋放之類的問題了,但是,這樣就萬無一失了嗎?
答案顯然不是的,在智能指針與常規指針轉換的過程中,我們仍需要注意一些坑。
1.常規指針轉換為智能指針:
①.new的普通指針與shared_ptr轉換:
如圖所示,這會發生什么情況?答案是輸出的會是隨機數,因為經過func函數后,我們用p初始化的臨時智能指針已經被析構了,引用計數先+1,后-1。所以經過func函數后,
p指向的對象被釋放,再解引用自然無法得到我們想要的結果。
#include<iostream> #include <memory> using namespace std; void func(shared_ptr<int>) { ; } int main() { int a = 5; auto p = new int(5); func(shared_ptr<int>(p)); cout << *p << endl; return 0; }
這種情況下,正確的做法如圖所示:一開始就使用智能指針。
#include<iostream> #include <memory> using namespace std; void func(shared_ptr<int>) { ; } int main() { //int a = 5; auto p = make_shared<int>(5); func(shared_ptr<int>(p)); cout << *p << endl; return 0; }
②.指向棧的指針與shared_ptr轉換:
如圖所示,這種情況,程序會直接崩潰,因為智能指針試圖釋放保存在棧上的變量,它越界了。
#include<iostream> #include <memory> using namespace std; void func(shared_ptr<int>) { ; } int main() { int a = 5; auto p = &a; func(shared_ptr<int>(p)); cout << *p << endl; return 0; }
2.智能指針向常規指針的轉換
我們通常使用get()函數向智能指針索要所指向對象的擁有權,但是這樣有時也會造成錯誤:
auto p = make_shared<int>(42); int* iPtr = p.get(); { shared_ptr<int>(iPtr); } int value = *p; // Error! 內存已經被釋放
p與iPtr指向了相同的內存,然而通過get方法后,將內存管理權轉移給了普通指針。iPtr傳遞給里面程序塊的臨時智能指針后,引用計數為1,隨后出了作用域,減少為0,釋放內存。