shared_ptr

<1> 类模板说明

 namespace boost
{
class bad_weak_ptr: public std::exception;
template<class T> class weak_ptr;
template<class T> class shared_ptr
{
public:
typedef T element_type;
1.1 构造与析构
/* 1.1.1 默认构造 */
说明:构造一个空的shared_ptr
结果:use_count() == && get() ==
shared_ptr(); // never throws
shared_ptr(std::nullptr_t); // never throws
/* 1.1.2 指针构造 */
说明:Y必须是一个完整的类型,Y*应该可以转换为T*。p必须是通过new分配的指针或者0。
结果:use_count() == && get() == p
template<class Y> explicit shared_ptr(Y * p);
/* 1.1.3 带有析构器的构造 */
说明:构造一个包含指针p和析构器d的shared_ptr。
结果:use_count() == && get() == p
template<class Y, class D> shared_ptr(Y * p, D d);
template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
template<class D> shared_ptr(std::nullptr_t p, D d);
template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
/* 1.1.4 复制和转换构造 */
说明:Y*应该可以转换为T*。如果r为空,则构造一个空的shared_ptr;否则构造一个与r同样拥有权的shared_ptr
结果:use_count() == r.use_count() && get() == r.get()
shared_ptr(shared_ptr const & r); // never throws
template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
/* 1.1.5 移动构造 */
说明:Y*应该可以转换为T*。
结果:*this包含r中的旧值,r == && r.get() ==
shared_ptr(shared_ptr && r); // never throws
template<class Y> shared_ptr(shared_ptr<Y> && r); // never throws
/* 1.1.6 别名构造 */
说明:构造一个shared_ptr,与r同样的拥有权,并且包含p
结果:use_count() == r.use_count() && get() == p
template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p); // never throws
/* 1.1.7 weak_ptr构造 */
说明:Y*应该可以转换为T*。构造一个shared_ptr,与r同样的拥有权,并且包含一个r中指针的副本
结果:use_count() == r.use_count()
template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
/* 1.1.8 auto_ptr构造 */
说明:Y*应该可以转换为T*。
结果:use_count() ==
template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
template<class Y> shared_ptr(std::auto_ptr<Y> && r);
/* 1.1.9 unique_ptr构造 */
说明:Y*应该可以转换为T*。等价于shared_ptr(r.release(), r.get_deleter())
结果:use_count() ==
template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
/* 1.1.10 析构函数 */
说明:
如果*this为空,或者拥有其他shared_ptr实例的控制权(use_count() > ),那么什么都不做;
如果*this拥有一个指针p和一个析构器d,那么调用d(p);
如果*this拥有一个指针p,那么调用delete p。
~shared_ptr(); // never throws
1.2 赋值操作符
说明:等价于shared_ptr(r).swap(*this),返回*this。
shared_ptr & operator=(shared_ptr const & r); // never throws
template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r); 说明:等价于shared_ptr(std::move(r)).swap(*this),返回*this。
shared_ptr & operator=(shared_ptr const && r); // never throws
template<class Y> shared_ptr & operator=(shared_ptr<Y> const && r); // never throws
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
说明:等价于shared_ptr().swap(*this),返回*this。
shared_ptr & operator=(std::nullptr_t); // never throws
1.3 重置操作
说明:等价于shared_ptr().swap(*this)。
void reset(); // never throws
说明:等价于shared_ptr(p).swap(*this)。
template<class Y> void reset(Y * p);
说明:等价于shared_ptr(p, d).swap(*this)。
template<class Y, class D> void reset(Y * p, D d);
说明:等价于shared_ptr(p, d, a).swap(*this)。
template<class Y, class D, class A> void reset(Y * p, D d, A a);
说明:等价于shared_ptr(r, p).swap(*this)。
template<class Y> void reset(shared_ptr<Y> const & r, element_type * p); // never throws
1.4 间接操作
T & operator*() const; // never throws; only valid when T is not an array type
T * operator->() const; // never throws; only valid when T is not an array type element_type & operator[](std::ptrdiff_t i) const; // never throws; only valid when T is an array type
1.5 逻辑运算
说明:如果a.get() == b.get(),则返回true。
template<class T, class U>
bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
说明:如果a.get() != b.get(),则返回true。
template<class T, class U>
bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws template<class T, class U>
bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
说明:如果p.get() == ,则返回true。
template<class T>
bool operator==(shared_ptr<T> const & p, std::nullptr_t); // never throws
template<class T>
bool operator==(std::nullptr_t, shared_ptr<T> const & p); // never throws
说明:如果p.get() != ,则返回true。
template<class T>
bool operator!=(shared_ptr<T> const & p, std::nullptr_t); // never throws
template<class T>
bool operator!=(std::nullptr_t, shared_ptr<T> const & p); // never throws
1.6 其他操作
说明:返回原始指针。
element_type * get() const; // never throws
说明:如果use_count() == ,则返回true,效率比use_count()高。
bool unique() const; // never throws
说明:返回shared_ptr的引用计数。
long use_count() const; // never throws
explicit operator bool() const; // never throws
说明:交换两个智能指针的内容。
void swap(shared_ptr & b); // never throws template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const; // never throws
template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const; // never throws
}; 说明:等价于a.swap(b)。
template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
说明:返回p.get()。
template<class T> typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p); // never throws
说明:几种转换操作。
template<class T, class U>
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
template<class T, class U>
shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
template<class T, class U>
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws
template<class T, class U>
shared_ptr<T> reinterpet_pointer_cast(shared_ptr<U> const & r); // never throws
说明:执行os << p.get(),返回os。
template<class E, class T, class Y>
std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
说明:返回者p对应的析构器d或者0。
template<class D, class T>
D * get_deleter(shared_ptr<T> const & p);
}

<2> 示例用法

示例 [1]:(基本用法)

 // shared_ptr1.cc
#include <vector>
#include <set>
#include <iostream>
#include <algorithm>
#include <boost/shared_ptr.hpp> // The application will produce a series of
// objects of type Foo which later must be
// accessed both by occurrence (std::vector)
// and by ordering relationship (std::set). struct Foo
{
Foo( int _x ) : x(_x) {}
~Foo() { std::cout << "Destructing a Foo with x=" << x << "\n"; }
int x;
/* ... */
}; typedef boost::shared_ptr<Foo> FooPtr; struct FooPtrOps
{
bool operator()( const FooPtr & a, const FooPtr & b )
{ return a->x > b->x; }
void operator()( const FooPtr & a )
{ std::cout << a->x << "\n"; }
}; int main()
{
std::vector<FooPtr> foo_vector;
std::set<FooPtr,FooPtrOps> foo_set; // NOT multiset! FooPtr foo_ptr( new Foo( ) );
foo_vector.push_back( foo_ptr );
foo_set.insert( foo_ptr ); foo_ptr.reset( new Foo( ) );
foo_vector.push_back( foo_ptr );
foo_set.insert( foo_ptr ); foo_ptr.reset( new Foo( ) );
foo_vector.push_back( foo_ptr );
foo_set.insert( foo_ptr ); foo_ptr.reset ( new Foo( ) );
foo_vector.push_back( foo_ptr );
foo_set.insert( foo_ptr ); std::cout << "foo_vector:\n";
std::for_each( foo_vector.begin(), foo_vector.end(), FooPtrOps() ); std::cout << "\nfoo_set:\n";
std::for_each( foo_set.begin(), foo_set.end(), FooPtrOps() );
std::cout << "\n" << "the program is done..." << "\n\n";
} // output
foo_vector: foo_set: the program is done... Destructing a Foo with x=
Destructing a Foo with x=
Destructing a Foo with x=
Destructing a Foo with x=

示例 [2]:(惯用法)使用shared_ptr来隐藏不完整类型的实现细节。

 // shared_ptr2.hpp
#include <boost/shared_ptr.hpp> // This example demonstrates the handle/body idiom (also called pimpl and
// several other names). It separates the interface (in this header file)
// from the implementation (in shared_ptr_example2.cpp). // Note that even though example::implementation is an incomplete type in
// some translation units using this header, shared_ptr< implementation >
// is still valid because the type is complete where it counts - in the
// shared_ptr_example2.cpp translation unit where functions requiring a
// complete type are actually instantiated. class example
{
public:
example();
void do_something();
private:
class implementation;
boost::shared_ptr< implementation > _imp; // hide implementation details
}; // shared_ptr2.cc
#include "shared_ptr2.hpp"
#include <iostream> class example::implementation
{
public:
~implementation() { std::cout << "destroying implementation\n"; }
}; example::example() : _imp( new implementation ) {} void example::do_something()
{ std::cout << "use_count() is " << _imp.use_count() << "\n"; } // shared_ptr2_test.cc
#include "shared_ptr2.hpp" int main()
{
example a;
a.do_something();
example b(a);
b.do_something();
example c;
c = a;
c.do_something();
return ;
} // output
use_count() is
use_count() is
destroying implementation
use_count() is
destroying implementation

示例 [3]:(线程安全性)一个shared_ptr实例可以同时被多个线程<read>(使用const操作访问);不同shared_ptr实例可以同时被多个线程<write>(使用mutable操作访问,例如operator=、reset);如果多个线程需要同时写同一个shared_ptr实例,则需要加锁保护。

 shared_ptr<int> p(new int());

 //--- Example 1 ---
// thread A
shared_ptr<int> p2(p); // reads p
// thread B
shared_ptr<int> p3(p); // OK, multiple reads are safe //--- Example 2 ---
// thread A
p.reset(new int()); // writes p
// thread B
p2.reset(); // OK, writes p2 //--- Example 3 ---
// thread A
p = p3; // reads p3, writes p
// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write //--- Example 4 ---
// thread A
p3 = p2; // reads p2, writes p3
// thread B
// p2 goes out of scope: undefined, the destructor is considered a "write access" //--- Example 5 ---
// thread A
p3.reset(new int());
// thread B
p3.reset(new int()); // undefined, multiple writes

weak_ptr

<1> 类模板说明

 namespace boost
{
template<class T> class weak_ptr
{
public:
typedef T element_type;
说明:构造一个空的weak_ptr,使得use_count() ==
weak_ptr();
说明:use_count() == r.use_count()
template<class Y> weak_ptr(shared_ptr<Y> const & r);
weak_ptr(weak_ptr const & r);
template<class Y> weak_ptr(weak_ptr<Y> const & r); ~weak_ptr();
说明:等价于weak_ptr(r).swap(*this)。
weak_ptr & operator=(weak_ptr const & r);
template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);
说明:如果*this为空,返回0;否则返回shared_ptr对象中的引用计数。
long use_count() const;
说明:如果use_count() == ,返回true。
bool expired() const;
说明:返回expired()? shared_ptr<T>(): shared_ptr<T>(*this)。
shared_ptr<T> lock() const;
说明:等价于weak_ptr().swap(*this)。
void reset();
void swap(weak_ptr<T> & b);
}; template<class T, class U>
bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b); template<class T>
void swap(weak_ptr<T> & a, weak_ptr<T> & b);
}

总结

<1> 关于shared_ptr:

shared_ptr类模板用于管理一个动态分配对象的指针(典型地,通过C++中的new表达式)。当所指对象的引用计数为0时,自动调用所指对象的析构函数。在调用析构函数时,是根据构造shared_ptr时传入的指针类型,而非模板参数,如:

shared_ptr<void> p(new int(5));  析构时调用int*类型的析构函数,而非void*类型。

从boost 1.53开始,shared_ptr可以被用来管理动态分配的数组的指针,传入模板参数是可以指定数组的大小,也可以不指定,没什么太大的区别,如下:

shared_ptr<double[1024]> p1(new double[1024]);

shared_ptr<double []> p2(new double[1024]);

由于使用了引用计数,那么可能会造成循环引用的问题。如下为示例程序:

 // shared_ptr3_cycles.cc
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm> using namespace std; class Controller
{
public:
explicit Controller(int i) : num(i) ,status("On")
{
cout << "Creating Controller" << num << endl;
} ~Controller()
{
cout << "Destroying Controller" << num << endl;
} // Demonstrates how to test whether the pointed-to memory still exists or not.
void checkStatuses() const
{
for_each
(others.begin(), others.end(),
[](weak_ptr<Controller> wp)
{
try
{
auto p = wp.lock();
cout << "status of " << p->num << " = " << p->status << endl;
}
catch (bad_weak_ptr b)
{
cout << "null object" << endl;
}
}
);
} int num;
string status;
vector<shared_ptr<Controller> > others;
//vector<weak_ptr<Controller> > others; // 使用weak_ptr避免循环引用
// Controller 对象表示设备控制器
// 由于每个控制器必须能够在任何时间查询其他控制器的状态,因此包含 vector<weak_ptr<Controller> >
}; void RunTest()
{
vector<shared_ptr<Controller> > v; v.push_back(shared_ptr<Controller>(new Controller()));
v.push_back(shared_ptr<Controller>(new Controller()));
v.push_back(shared_ptr<Controller>(new Controller())); // Each controller depends on all others not being deleted.
// Give each controller a pointer to all the others.
for (int i = ; i < v.size(); ++i)
{
for_each
(v.begin(), v.end(),
[v,i](shared_ptr<Controller> p)
{
if(p->num != i)
{
v[i]->others.push_back(shared_ptr<Controller>(p));
// v[i]->others.push_back(weak_ptr<Controller>(p));
cout << "push_back to v[" << i << "]: " << p->num << endl;
}
}
);
} for_each
(v.begin(), v.end(),
[](shared_ptr<Controller>& p)
{
cout << "use_count = " << p.use_count() << endl;
p->checkStatuses();
}
);
} int main()
{
RunTest();
return ;
}

上述程序运行结果如下:

 // output
Creating Controller1
Creating Controller2
Creating Controller3
push_back to v[]:
push_back to v[]:
push_back to v[]:
push_back to v[]:
push_back to v[]:
push_back to v[]:
push_back to v[]:
use_count =
status of = On
status of = On
status of = On
use_count =
status of = On
status of = On
use_count =
status of = On
status of = On

可以发现,上述程序由于出现了循环引用问题,导致析构函数没有调用,如果程序中使用vector<weak_ptr<Controller> > others记录其他控制器的状态,由于不涉及引用计数的增加,因此use_count函数永远返回1,这样就打破了循环引用,只需修改上述程序中注释掉的两行即可,修改后运行结果如下:

 Creating Controller3
push_back to v[]:
push_back to v[]:
push_back to v[]:
push_back to v[]:
push_back to v[]:
push_back to v[]:
push_back to v[]:
use_count =
status of = On
status of = On
status of = On
use_count =
status of = On
status of = On
use_count =
status of = On
status of = On
Destroying Controller1
Destroying Controller2
Destroying Controller3

<2> 关于weak_ptr:

weak_ptr类模板存储一个shared_ptr管理的对象的<弱引用>,即可以访问shared_ptr拥有的对象,但是不参与引用计数。如果程序中需要观察某个对象的状态,最好使用weak_ptr。同时weak_ptr也可以断开shared_ptr对象之间的循环引用。为了访问这个对象,可以使用shared_ptr构造函数将weak_ptr转换为一个shared_ptr(也可以使用weak_ptr的成员函数lock来转换)。如果shared_ptr管理的对象已经被析构,此时使用转换操作,那么shared_ptr的转换构造将抛出boost::bad_weak_ptr异常,而weak_ptr::lock将返回一个空的shared_ptr。

与shared_ptr相比,weak_ptr提供了非常有限的操作,因为在多线程程序中操作weak_ptr比较危险。shared_ptr中有一个get函数用于返回一个原始指针,如下是一种错误的用法:

shared_ptr<int> p(new int(5));

weak_ptr<int> q(p);

// ...

if (int* r = q.get())

{

// use *r

}

如果在if语句后,使用r前,有另一个线程执行了:p.reset(),那么r就变为了空悬指针(dangling pointer),解决方法是利用weak_ptr中的lock函数创建一个q的临时shared_ptr:

shared_ptr<int> p(new int(5));

weak_ptr<int> q(p);

// ...

if (shared_ptr<int> r = q.lock())

{

// use *r

}

shared_ptr & weak_ptr的更多相关文章

  1. stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结

    stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结 1. auto_ptrauto_ptr主要是用来解决资源自动释放的问题,比如如下代码:voi ...

  2. shared_ptr / weak_ptr 代码片段

    参考<<Boost程序库完全开放指南>> shared_ptr  类摘要(只列出了常用的部分)和相关说明 template <class T> class shar ...

  3. boost shared_ptr weak_ptr

    文档: http://www.boost.org/doc/libs/1_57_0/libs/smart_ptr/shared_ptr.htm shared_ptr构造有个原型 template< ...

  4. C++ 智能指针(shared_ptr/weak_ptr)原理分析

    其主要的类关系如下所示(省略相关的类模板参数): 图1 从上面的类图可以清楚的看出shared_ptr内部含有一个指向被管理对象(managed object)T的指针以及一个__shared_cou ...

  5. auto_ptr,unique_ptr,shared_ptr,weak_ptr

    http://mojijs.com/2016/08/218129/index.html http://www.cnblogs.com/lanxuezaipiao/p/4132096.html

  6. 关于shared_ptr与weak_ptr的使用(good)

    shared_ptr是带引用计数的智能指针,可以说大部分的情形选择用shared_ptr不会出问题.那么weak_ptr是什么,应该怎么用呢? weak_ptr也是智能指针,但是比较弱,感觉没什么用. ...

  7. 智能指针shared_ptr新特性shared_from_this及weak_ptr

    enable_shared_from_this是一个模板类,定义于头文件<memory>,其原型为: template< class T > class enable_shar ...

  8. shared_ptr&scoped_ptr&weak_ptr

    [RAII - Resource Acquisition Is Initialization] 获得一个资源的时候,不管这个资源是对象.内存.文件句柄或者其它什么,你都要在一个对象的构造函数中获得它, ...

  9. 智能指针 auto_ptr、scoped_ptr、shared_ptr、weak_ptr

    什么是RAII? RAII是Resource Acquisition Is Initialization的简称,是C++语言的一种管理资源.避免泄漏的惯用法. RAII又叫做资源分配即初始化,即:定义 ...

随机推荐

  1. linuxshell中"2>&1"含义

    http://blog.sina.com.cn/s/blog_652819220100wpvu.html

  2. iOS触摸事件哦

    主要是记录下iOS的界面触摸事件处理机制,然后用一个实例来说明下应用场景. 一.处理机制 界面响应消息机制分两块,(1)首先在视图的层次结构里找到能响应消息的那个视图.(2)然后在找到的视图里处理消息 ...

  3. LNMP架构

    LNMP架构介绍 lnmp里的php会启动一个服务,nginx把用户请求的php交给php-fpm处理,比如登录网站php要和mysql做交互,查用户的账号和密码,处理完之后,php-fpm会告诉ng ...

  4. Django中的 动态URL配置

    举个例子,一家在线书店会为每一本书提供一个URL,如:/books/243/./books/81196/. 让我们创建第三个视图来显示当前时间和加上时间偏差量的时间,设计是这样的: /time/plu ...

  5. ultragrid checkbox

    울트라그리드에 체크박스 넣을 사용하는 속성. cols["checked"].Header.Caption = ""; cols["checked ...

  6. context.Request.Files post 上传问题件

    [无刷新上传] 要实现文件上传,form必须设置几个属性:1.action:设为要处理数据的页面地址:2.method:设为"post":3.enctype/encoding:必须 ...

  7. Atitit.ati  str  字符串增强api

    Atitit.ati  str  字符串增强api 1. java StringUtils方法全览 分类: Java2011-11-30 17:22 8194人阅读 评论(2) 收藏 举报 javas ...

  8. poj3253 优先队列

    Farmer John wants to repair a small length of the fence around the pasture. He measures the fence an ...

  9. Ubuntu下修改tomcat6默认的8080端口

    $ sudo vi /etc/tomcat6/server.xml   将 <Connector port="8080" protocol="HTTP/1.1&qu ...

  10. android studio 中配置androidAnnotation 的新版正确配置

    apply ].processResources.manifestFile resourcePackageName 'com.peiandsky.firstandroidstudio' }}