Table of Contents
使用C++11解决内存泄漏的问题
shared_ptr
1.初始化
可以通过构造函数、std::make_shared<T>
和reset方法来初始化shared_ptr
。
优先使用make_shared
来构造shared_ptr
,因为它更加高效。
不能将一个原始指针直接赋值给一个shared_ptr
:
std::shared_ptr<int> p = new int(); //错误
2.获取原始指针
3.指定删除器
void DeleteIntPtr(int* p)
{
delete p;
}
std::shared_ptr<int> p(new int, DeleteIntPtr);
当用shared_ptr
管理动态数组时,需要指定删除器,因为std::shared_ptr
的默认删除器不支持数组对象。
std::shared_ptr<int> p(new int[10], [](int* p){detele[] p;});
也可以将std::default_detele
作为删除器。default_delete
通过调用delete
来实现删除。
std::shared_ptr<int> p(new int[10], std::default_delete<int[]>);
为什么shared_ptr
需要显示指定数组的删除器呢?大概是因为shared_ptr
的模板参数类型是一个固定的T
,shared_ptr
的模板代码无法区分T*
指向的是单个元素指针还是数组指针吧。
4.使用shared_ptr需要注意的地方
- 不要用一个原始指针去初始化多个
shared_ptr
,这样多个shared_ptr
管理同一个资源,析构的时候会多次删除这个对象。 - 不要在函数实参中创建
shared_ptr
。
function(shared_ptr<int>(new int), g());
像上面的代码,会先执行new int
,但是shared_ptr<int>()
和g()
的执行顺序是没有规定的,因此可能出现g()
先执行,但是g()
抛异常,然后shared_ptr
未创建成功,new int
的内存就泄漏了。
- 通过
shared_from_this
返回this
指针。
当类A被share_ptr管理,且在类A的成员函数里需要把当前类对象作为参数传给其他函数时,就需要传递一个指向自身的share_ptr
。
我们可能会想给类添加一个从this
指针生成shared_ptr
的成员函数,但是这会导致一些问题,因为我们可能会在代码中手动创建该类对象的shared_ptr
,然后又调用该对象的生成shared_ptr
的成员函数,这样这个对象就有了两个shared_ptr
在管理它,就会出问题。
struct A {
shared_tr<A> GetSelf() {
return shared_ptr<A>(this);
}
};
int main()
{
shared_ptr<A> sp1(new A);
shared_ptr<A> sp2 = sp1->GetSelf(); // 生成了两个shared_ptr管理同一个对象
return 0;
}
正确的做法是继承std::enable_shared_from_this
模板类。
class A: public std::enable_shared_from_this<A>
{
std::shared_ptr<A> GetSelf() {
return shared_from_this();
}
};
std:shared_ptr<A> spy(new A);
std::shared_ptr<A> p = spy->GetSelf();
https://en.cppreference.com/w/cpp/memory/enable_shared_from_this
A common implementation for
enable_shared_from_this
is to hold a weak reference (such as std::weak_ptr) to this. The constructors of std::shared_ptr detect the presence of an unambiguous and accessible (ie. public inheritance is mandatory) (since C++17)enable_shared_from_this
base and assign the newly created std::shared_ptr to the internally stored weak reference if not already owned by a live std::shared_ptr (since C++17). Constructing a std::shared_ptr for an object that is already managed by another std::shared_ptr will not consult the internally stored weak reference and thus will lead to undefined behavior.It is permitted to call
shared_from_this
only on a previously shared object, i.e. on an object managed by std::shared_ptr<T>. Otherwise the behavior is undefined (until C++17)std::bad_weak_ptr is thrown (by the shared_ptr constructor from a default-constructedweak_this
) (since C++17).
enable_shared_from_this
provides the safe alternative to an expression like std::shared_ptr<T>(this), which is likely to result in this being destructed more than once by multiple owners that are unaware of each other (see example below)
如上面所述,shared_from_this
还只能被shared_ptr<T>
这样的智能指针调用。
- 通过使用
weak_ptr
避免shared_ptr
的循环引用。
unique_ptr
unique_ptr
不允许复制,但是可以通过函数返回给其他的unique_ptr
,还可以通过std::move
来转移到其他的unique_ptr
,这样它本身就不再拥有原来指针的所有权了。
unique_ptr
指定删除器时与shared_ptr
不一样,需要指定删除器的类型。
std::unique_ptr<int, void(*)(int *)> ptr(new int(1), [](int *p){delete p;});
weak_ptr
- 通过
use_count()
获取当前观测资源的引用计数 - 通过
expired()
方法获取当前观测资源是否已经被释放 - 解决循环引用
- 通过
shared_from_this
返回this
指针
近期评论