C++11 shared_ptr共享智能指针
2017-07-06 15:30
459 查看
前言
std::shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。在最后一个shared_ptr析构的时候,内存才会释放。1. shared_ptr基本使用方法
1.1 初始化
#include <memory> //智能指针初始化 std::shared_ptr<int> p(new int(20)); cout << *p << endl; std::shared_ptr<int> p2 = p; cout << *p2 << endl; std::shared_ptr<int> p3 = std::make_shared<int>(); *p3 = 1024; cout << *p3 << endl; p3.reset(new int(-1)); cout << *p3 << endl; std::shared_ptr<int> p4; if(p4) { cout << "ptr is null" << endl; }应当优先使用make_shared来构造只能指针,因为它更加高效。但是不能讲一个原始指针直接赋值给一个智能指针,例如,下面的这种情况就是错误的
std::shared_ptr<int> p = new int(20);上面的代码会在编译的时候报错,不允许直接赋值。从上面的例子中可以看到智能指针的用法和普通指针的用法类似,只不过不需要自己管理分配的内存。shared_ptr不能通过直接将原始指针赋值来初始化,需要通过构造函数或是辅助方法来初始化。对于一个未初始化的智能指针,可以通过reset方法来初始化,当智能指针中有值的时候,调用reset会使引用计数减1。另外之智能指针可以通过重载bool类型操作符来判断智能指针是否为空(未被初始化)。
1.2 获取原始指针
使用get方法来返回原始指针std::shared_ptr<int> p(new int(20)); int *pp = p.get();
1.3 指定删除器
智能指针的删除支持自定义删除函数,用法如下://自定义的删除智能指针函数 void MyDeleteIntPtr(int *p) { cout << __FUNCTION__ << "delte ptr" << endl; delete p; p = nullptr; } //创建智能指针 void MyMakeIntPtr() { cout << __FUNCTION__ << "make ptr" << endl; std::shared_ptr<int> P(new int(1034), MyDeleteIntPtr); //指定删除的函数 cout << "value:" << *P << endl; } MyMakeIntPtr(); //调用但是这样的方式未免太过于麻烦了,那么可以写成这样的(使用lambda表达式)
void MyMakeIntPtr() { cout << __FUNCTION__ << "make ptr" << endl; std::shared_ptr<int> P(new int(1034), [](int *p){ cout << __FUNCTION__ << "delte ptr" << endl; delete p; p = nullptr;}); //指定删除的lambda表达式 cout << "value:" << *P << endl; }这里调用的函数也就是仿函数了。当使用shared_ptr管理动态数组时,需要制定删除器,因为std::shared_ptr的默认删除器不支持数组对象。使用的代码如下:
std::shared_ptr<int> P(new int[1034], [](int *p){ cout << __FUNCTION__ << "delte ptr" << endl; delete[] p; p = nullptr;}); //指定删除的lambda表达式
也可以使用自带的std::default_delete作为删除器。default-delete的内部是通过调用delete来实现功能的,代码如下:
std::shared_ptr<int> P(new int[1034], std::defualt_delete<int[]>);
2. shared_ptr注意事项
只能只恨虽然能够自动管理内存,但它还是有不少缺陷,在使用时需要注意一下几点2.1 不要使用一个原始指针去初始化多个shared_ptr
int * ptr = new int(1024); std::shared_ptr<int> P(ptr); std::shared_ptr<int> P1(ptr); //错误
2.2 不要再函数参数实参中创建shared_ptr
function(shared_ptr<int>(new int), g());上面的函数中写法是有缺陷的。这是因为C++的参数计算顺序在不同的编译器不同的调用约定下可能是不一样的,一般是从右到左,但是也有可能是从左到右,所以,可能的过程是先new int,然后调用g()。但是如果恰好g()发生了异常,而shared_ptr<int>还没有创建,则int内存就泄露了,正确的写法应该是这样的
shared_ptr<int> p(new int); function(p, g());
2.3 通过shared_ptr返回this指针
struct A { std::shared_ptr<A> GetSelf() { return std::shared_ptr<A>(this); //错误 } }; shared_ptr<A> p1(new A()); shared_ptr<A> p2 = p1->GetSelf();不要讲this指针作为shared_ptr返回出来,因为this指针本质上是一个裸指针,因此,这样可能会导致重复析构。在上面的代码中构造了两个智能指针,当离开作用域之后this指针就会被两个智能指针各自析构,导致重复析构的问题。正确的使用方式是
struct A: public std::enable_shared_from_this<A> { std::shared_ptr<A> GetSelf() { return shared_from_this(); } }; shared_ptr<A> p1(new A()); shared_ptr<A> p2 = p1->GetSelf(); //正确
4. 避免循环引用
struct A { std::shared_ptr<B> aptr; ~A() {} }; struct B { std::shared_ptr<A> aptr; ~B() {} }; shared_ptr<A> p1(new A()); shared_ptr<B> p2(new B()); p1->bptr = p2; p2->aptr = p1;上面的两个智能指针在构造的时候引用计数为1,但是在循环引用之后就变为了2 。在离开作用域之后两个只能指针减1,但是并不会变为0,导致两个只能指针不会被析构,产生内存泄露。解决办法是把A和B任何一个成员变量改为weak_ptr。
相关文章推荐
- C++11 FAQ中文版:共享资源的智能指针——shared_ptr
- C++11 FAQ中文版:共享资源的智能指针——shared_ptr
- 【C++11】新特性——共享资源的智能指针shared_ptr
- C++11 FAQ中文版:共享资源的智能指针——shared_ptr
- C++11 Intro - C++11智能指针之shared_ptr、weak_ptr
- 【C++11新特性】 C++11智能指针之shared_ptr
- C++11 智能指针之 std::shared_ptr 初级学习
- C++11智能指针之使用shared_ptr实现多态
- 【C++11新特性】 C++11智能指针之shared_ptr
- (转载)【C++11新特性】 C++11智能指针之shared_ptr
- 多索引容器boost::multi_index_container储存共享智能指针boost::shared_ptr
- C++11 智能指针 shared_ptr
- c++11:智能指针之shared_ptr
- C++11智能指针之shared_ptr、weak_ptr
- shared_ptr 共享指针 智能指针 简介
- 【C++11新特性】 C++11智能指针之shared_ptr
- 【C++11新特性】 C++11智能指针之shared_ptr
- C++11智能指针之std::shared_ptr
- C++11 智能指针——shared_ptr
- C++11 shared_ptr 智能指针 的使用,避免内存泄露