一、为什么需要智能指针
智能指针是为了解决动态内存的使用很容易出错的问题。c++原始的动态内存管理是通过new和delete这一对运算符来完成的,但是它们的使用经常容易出错。总的来说,它们有以下三个常见的问题:
1、忘记delete内存
这样常常导致人们所说的“内存泄漏”问题,因为这种内存永远不可能归还和释放,而且这种问题只有等程序运行很长时间,等内存耗尽之后才能检测到。看下面的一个例子:
Foo *factory(T arg)
{
return new Foo(arg);
}
void use_factory(T arg)
{
Foo *p = factory(arg);
// 使用p,但是不delete它
// p离开了它的作用域,但是它指向的内存没有释放;
}
factory函数在堆上申请Foo大小的空间,use_factory使用这块空间,但是离开了use_factory函数体之前,并没有释放这块空间,因为p是唯一指向这块空间的指针,一旦use_factory函数返回,没人会知道这块空间到底是什么,这样导致这块空间的地址丢失,使这块空间永远无法释放。
2、使用已经释放掉的对象
当我们delete一个指针之后,指针值变为无效了,但是这个指针任然保留着之前的地址。为了防止我们再使用这个无效的地址,一般有两种做法:一种是利用作用域,在这个作用域之内释放掉内存,离开了作用域就无法再访问这个指针;另一种是将这个指针设置为nullprt。但是第二种做法还是具有潜在的问题:
int *p(new int(42));
auto q = p;
delete p;
p = nullptr;
这样在delete p之后也将p设置为nullptr,但是这样就万事大吉了吗?不是的,我们还可以通过q访问这个无效的地址。。。
3、对同一块内存释放两次
当有两个指针指向同一个动态分配的对象时,就会出现这样的问题。
二、智能指针的用法
智能指针有四种:auto_ptr, shared_ptr, unique_ptr, weak_ptr。C++11中支持后三种。
shared_ptr与unique_ptr共享的操作
shared_ptr独有的操作
unique_ptr独有的操作
weak_ptr独有的操作
简单来说shared_ptr指向某一个对象,可以和多个shared_ptr共同指向同一个对象,他们共同维持一个引用计数,当引用计数为0,说明没有shared_ptr指向这个对象,不需要他了,就自动释放内存。
unique_ptr是“独占一个对象”,当它被销毁,它所指的对象也被销毁。
weak_ptr是相对于shared_ptr而言的,如果说shared_ptr是“铁丝”绑在对象上,那么weak_ptr就是“棉线”粘在对象上的,不会增加shared_ptr的引用计数,最后一个shared_ptr要释放该对象,即使有weak_ptr指向它,也会进行释放,不会考虑weak_ptr的感受。。
三、智能指针就真的安全吗?
智能指针很好用,但是它也不是绝对安全的,我们要知道其中的陷阱。
1、不要混合使用普通指针和智能指针
void process(shared_ptr<int> ptr)
{
//使用ptr
// ptr离开作用域,被销毁
}
int *x(new int(1024));
process(x);//错误,不能将int*转化成shared_ptr
process(shared ptr<int>(x));//可以,但是会释放内存
int j = x; // 未定义,x是一个空悬指针
在这里,process(shared ptr (x))将普通指针显示构造了一个临时的shared_ptr,此时它的引用计数为1。离开了这个函数体之后,这个临时的shared_ptr会被销毁,此时引用计数为0,所以也会把x这块区域给销毁。。
2、不要使用get初始化另一个智能指针或为智能指针赋值
shared_ptr <int> p(new int(42));
int *q = p.get();
{
//新的作用域
//独立创建一个临时的shared_ptr
shared_ptr<int> (q);
}
int foo = *p;// 未定义:p指向的内存已经被销毁了
在这里,p,q指向相同的内存区域,但是因为他们是独立创建的,因此各自的引用计数为1。离开作用域之后会被销毁。导致p指向的内存区域无效。
一些tips:
1. 不适用相同的内置指针值初始化多个职能指针
2. 不delete get()返回的指针;
3. 不使用get() 初始化或reset()另一个智能指针;
4. 如果使用了get()返回的指针,记住当最后一个对应的智能指针销毁后,你的指针就变为无效了;
5. 如果你使用的智能指针管理的资源不是new分配的内存,记住传递给它一个删除器。
本文探讨了C++中智能指针的必要性,列举了三种常见内存管理问题:内存泄漏、使用已释放对象及重复释放内存。介绍了四种智能指针类型:shared_ptr, unique_ptr, weak_ptr及其使用场景,并给出了避免陷阱的建议。
1345

被折叠的 条评论
为什么被折叠?



