指针是柄双刃剑,用的好,就会威力倍增;用的稍有闪失,就会造成悲剧。
自从c++11引入智能指针shared_ptr后,我们似乎再也不用担心new的内存没有释放之类的问题了,但是,这样就万无一失了吗?
答案显然不是的,在智能指针与常规指针转换的过程中,我们仍需要注意一些坑。
1.常规指针转换为智能指针:
①.new的普通指针与shared_ptr转换:
如图所示,这会发生什么情况?答案是输出的会是随机数,因为经过func函数后,我们用p初始化的临时智能指针已经被析构了,引用计数先+1,后-1。所以经过func函数后,
p指向的对象被释放,再解引用自然无法得到我们想要的结果。
#include#include 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#include 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#include 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,释放内存。