C++11_智能指针
auto_ptr
-
解决什么问题
-
有什么问题
shared_ptr
- 解决问题
原来 c 里的思路,一个全局共享的对象,n 多地方可以用指针指向,并使用它,但谁来释放,何时释放?
如果用 shared_ptr,不用关心谁释放,最后 1 个 shared_ptr 失效,则该对象被释放。
shared_ptr
采用引用计数的方式管理所指向的对象。引用值代表当前有多少个 shared_ptr 引用了该对象。当引用值为 0 时,shared_ptr 将自动析构所引用的对象。
shared_ptr<Obj> ptr1(new Obj(1) ); // ref =1
shared_ptr<Obj> ptr2(new Obj(2) ); // ref =1
ptr1 = ptr2 ;
ptr2,ptr1 的引用对象均为 Obj(2)。新的引用导致 ptr1 的新对象 ref+1,旧的引用对象 ref-1,为 0,则调用 Obj()的析构;
可以尽情的用 share_ptr 代替 c 的裸指针,再也不用担心资源释放的问题,RAII 神器。
- make_shared
auto + make_shared 可以轻松创建 shared_ptr;
auto p = make_shared<T>(args) ;
unique_ptr
unique_ptr
对于所指向的对象,正如其名字所示,是 独占 的。所以,不可以对 unique_ptr 进行拷贝、赋值等操作,但是可以通过 release 函数在 unique_ptr 之间转移控制权。
release
是 unique 独有的,仅仅是剥离出原对象,即智能指针不再包裹
原对象。而不析构对象。
但有 2 个特殊情况,即 unique_ptr 可以作为函数的返回值和参数使用,这时虽然也有隐含的拷贝存在,但是并非不可行的。
unique_ptr<Obj> ptr1(new Obj(1) ); // ref =1
unique_ptr<Obj> ptr2(new Obj(2) ); // ref =1
unique_ptr<Obj> ptr3 = unique_ptr<Obj>(ptr1); // not allowed
ptr1 = ptr2 // not allowed
//交换两个unique_ptr的控制权
auto tmp = ptr1.release();
ptr1.reset(ptr2.release());
ptr2.reset(tmp);
unique_ptr<string> func(unique_ptr<string> ptr) {...}
auto ptr3 = func(ptr1); //ok
weak_ptr
weak_ptr
一般和 shared_ptr 配合使用。它可以指向 shared_ptr 所指向的对象,但是却不增加对象的引用计数。这样就有可能出现 weak_ptr 所指向的对象实际上已经被释放了的情况。因此,weak_ptr 有一个 lock 函数,尝试取回一个指向对象的 shared_ptr。
weak_ptr<Demo> weak_ptr_test()
{
auto shared = make_shared<Demo>("sunny");
auto weaked = weak_ptr<Demo>(shared);
cout << "shared show";
shared->show();
cout << "weak show";
auto result = weaked.lock();
if(result != NULL)
result->show();
shared.reset();
cout << "weak expired val after reset " << weaked.expired() << endl;
shared = make_shared<Demo>("rainy");
cout << "weak expired val after = " << weaked.expired() << endl;
return weaked;
}
auto weaked = weak_ptr_test();
cout << "weak expired val after returned " << weaked.expired() << endl;
执行结果为
Demo sunny created
shared showDemo sunny lived
weak showDemo sunny lived
weak expired val after reset 0
Demo rainy created
weak expired val after = 0
Demo sunny destroyed
Demo rainy destroyed
weak expired val after returned 1
共享指针里的 get,reset
get
表示拿到原始指针,此时原始对象还是包裹
在智能指针里的,但不推荐用 get 的方式去访问原对象。
reset
表示释放原引用对象,并 reset 为新的对象。
auto ptr = make_shared<string>("love");
string* orig = ptr.get(); //即orig 指向"love"
ptr.reset(new string("peace")); //释放原来的love,装载新的peace。