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. Python 爬虫之 BeautifulSoup

    简介 Beautiful Soup提供一些简单的.python式的函数用来处理导航.搜索.修改分析树等功能.它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出 ...

  2. django inspectdb

    使用inspectdb  --通过已有数据库表生成 model.pyinspectdb辅助工具检查你的settings文件指向的数据库,决定你表示你的表的Django模型并打印Python模型代码到标 ...

  3. bootstrap学习笔记一 登录水平表单

    先上效果图: 样式定义: <form class="form-horizontal"> <div class="control-group"& ...

  4. (MVC)从客户端中检测到有潜在危险的 Request.Form 值

    在传统的.net Request验证中 ,只需要在WebConfig HttpRuntime节点 加入 RequestValidateMode 属性,值为2.0(此处2.0并非Framework版本) ...

  5. Navicat for MySQL再谈之无奈之下还是去安装Navicat Premium

    不多说,直接上干货! 首先,Navicat for MySQL没有查看数据库属性. 其次,没有这个功能多和强大,在走过一段弯路之后,果断放弃Navicat for MySQL,而使用Navicat P ...

  6. JS -判断、监听屏幕横竖屏切换事件

    通过监听window.orientationchange事件,当横竖屏切换事件时触发 <!doctype html> <html> <head> <title ...

  7. Unable to verify your data submission错误解决

    如果不用Yii2提供的ActiveForm组件生成表单,而是自定义表单,那么当你提交表单的时候就会报这个错误 Unable to verify your data submission 这是因为Web ...

  8. 李洪强iOS经典面试题32-简单介绍 ARC 以及 ARC 实现的原理

    李洪强iOS经典面试题32-简单介绍 ARC 以及 ARC 实现的原理 问题 简单介绍 ARC 以及 ARC 实现的原理. 考查点 ARC 是苹果在 WWDC 2011 提出来的技术,因此很多新入行的 ...

  9. sqoop从hdfs 中导出数据到mysql

    bin/sqoop export \ --connect "jdbc:mysql://mini1:3306/study?useUnicode=true&characterEncodi ...

  10. win 7和虚拟机之间ping

    虚拟机的网卡和真实机的IP设为同一网段.用ping检查是否通,通了后用工具连接ssh看能否登录!如果成功的话winscp应该就能用了.如果不同就要就检查防火墙看是否开放了22端口,没有的话就要开放一下 ...