shared_ptr & weak_ptr
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的更多相关文章
- stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结
stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结 1. auto_ptrauto_ptr主要是用来解决资源自动释放的问题,比如如下代码:voi ...
- shared_ptr / weak_ptr 代码片段
参考<<Boost程序库完全开放指南>> shared_ptr 类摘要(只列出了常用的部分)和相关说明 template <class T> class shar ...
- boost shared_ptr weak_ptr
文档: http://www.boost.org/doc/libs/1_57_0/libs/smart_ptr/shared_ptr.htm shared_ptr构造有个原型 template< ...
- C++ 智能指针(shared_ptr/weak_ptr)原理分析
其主要的类关系如下所示(省略相关的类模板参数): 图1 从上面的类图可以清楚的看出shared_ptr内部含有一个指向被管理对象(managed object)T的指针以及一个__shared_cou ...
- auto_ptr,unique_ptr,shared_ptr,weak_ptr
http://mojijs.com/2016/08/218129/index.html http://www.cnblogs.com/lanxuezaipiao/p/4132096.html
- 关于shared_ptr与weak_ptr的使用(good)
shared_ptr是带引用计数的智能指针,可以说大部分的情形选择用shared_ptr不会出问题.那么weak_ptr是什么,应该怎么用呢? weak_ptr也是智能指针,但是比较弱,感觉没什么用. ...
- 智能指针shared_ptr新特性shared_from_this及weak_ptr
enable_shared_from_this是一个模板类,定义于头文件<memory>,其原型为: template< class T > class enable_shar ...
- shared_ptr&scoped_ptr&weak_ptr
[RAII - Resource Acquisition Is Initialization] 获得一个资源的时候,不管这个资源是对象.内存.文件句柄或者其它什么,你都要在一个对象的构造函数中获得它, ...
- 智能指针 auto_ptr、scoped_ptr、shared_ptr、weak_ptr
什么是RAII? RAII是Resource Acquisition Is Initialization的简称,是C++语言的一种管理资源.避免泄漏的惯用法. RAII又叫做资源分配即初始化,即:定义 ...
随机推荐
- Python 爬虫之 BeautifulSoup
简介 Beautiful Soup提供一些简单的.python式的函数用来处理导航.搜索.修改分析树等功能.它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出 ...
- django inspectdb
使用inspectdb --通过已有数据库表生成 model.pyinspectdb辅助工具检查你的settings文件指向的数据库,决定你表示你的表的Django模型并打印Python模型代码到标 ...
- bootstrap学习笔记一 登录水平表单
先上效果图: 样式定义: <form class="form-horizontal"> <div class="control-group"& ...
- (MVC)从客户端中检测到有潜在危险的 Request.Form 值
在传统的.net Request验证中 ,只需要在WebConfig HttpRuntime节点 加入 RequestValidateMode 属性,值为2.0(此处2.0并非Framework版本) ...
- Navicat for MySQL再谈之无奈之下还是去安装Navicat Premium
不多说,直接上干货! 首先,Navicat for MySQL没有查看数据库属性. 其次,没有这个功能多和强大,在走过一段弯路之后,果断放弃Navicat for MySQL,而使用Navicat P ...
- JS -判断、监听屏幕横竖屏切换事件
通过监听window.orientationchange事件,当横竖屏切换事件时触发 <!doctype html> <html> <head> <title ...
- Unable to verify your data submission错误解决
如果不用Yii2提供的ActiveForm组件生成表单,而是自定义表单,那么当你提交表单的时候就会报这个错误 Unable to verify your data submission 这是因为Web ...
- 李洪强iOS经典面试题32-简单介绍 ARC 以及 ARC 实现的原理
李洪强iOS经典面试题32-简单介绍 ARC 以及 ARC 实现的原理 问题 简单介绍 ARC 以及 ARC 实现的原理. 考查点 ARC 是苹果在 WWDC 2011 提出来的技术,因此很多新入行的 ...
- sqoop从hdfs 中导出数据到mysql
bin/sqoop export \ --connect "jdbc:mysql://mini1:3306/study?useUnicode=true&characterEncodi ...
- win 7和虚拟机之间ping
虚拟机的网卡和真实机的IP设为同一网段.用ping检查是否通,通了后用工具连接ssh看能否登录!如果成功的话winscp应该就能用了.如果不同就要就检查防火墙看是否开放了22端口,没有的话就要开放一下 ...