参考<<Boost程序库完全开放指南>>

shared_ptr  类摘要(只列出了常用的部分)和相关说明

 template <class T> class shared_ptr {
public:
typedef T element_type;
shared_ptr();
template<class Y> explicit shared_ptr(Y * p);
template<class Y, class D> shared_ptr(Y * p); // 定制删除器 d取代简单的delete. 要求能用d()函数方式调用, d可以是函数对象或者函数指针.
~shared_ptr(); shared_ptr(shared_ptr const & r);
template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r); //比较运算符的比较是基于内部保存的指针.return a.get() == b.get();
shared_ptr & operator = (shared_ptr const & r);
template<class Y> shared_ptr & operator = (shared_ptr<Y> const & r);
template<class Y> shared_ptr & operator = (std::auto_ptr<Y> & r); void reset(); // 将引用计数减一,停止当前指针对原始指针的共享.
template<class Y> void reset(Y * p); // 引用计数减一, 同时转而共享另一个指针.
template<class Y, class D> void reset(Y * p, D d); T & operator * () const;
T * operator -> () const;
T * get() const; // 获取原始指针 bool unique() const;//高效判断
long use_count() const; // 效率低, 建议只在调试时用. operator unspecified_bool_type() const; // 提供隐式类型转换, 比如放在条件语句中作为bool值
void swap(shared_ptr & b);//交换内部指针
};

1.  shared_ptr r 特点

  - 提供 * ->操作符模仿原始指针行为, 提供隐式bool 类型转换以判断指针的有效性.

  - 没有提供指针算术运算操作,除 < 运算符外. 所以可以用于标准容器.

  - 可以被安全共享, 提供基本的线程安全的保证(一个 shared_ptr 可以被多个线程安全读取).

  - 类型转换不能用诸如: static_cast<T*>(p.get())的形式(导致转换后指针无法再被 shared_ptr 自动管理),  shared_ptr 提供类似的转型函数:  static-pointer_cast<T>() ,  const_pointer_cast<T>()  ,  dynamic_pointer_cast<T>() .

 shared_ptr<std::exception> sp1 (new bad_exception("error"));
shared_ptr<bad_exception> sp2 = dynamic_pointer_cast<bad_exception>(sp1);
shared_ptr<std::exception> sp3 = static_pointer_cast<std::exception>(sp2);
assert(sp3 == sp1);

  - 支持 << 操作符, 直接打印内部指针的值, 方便调试.

  - 几乎可以100%在任何new 出现的地方接受new的动态分配结果, 然后被任意使用,完全消灭delete的使用的和内存泄露.

2.  shared_ptr  的使用技巧

  - 使用工厂函数 make_shared() 来包装new表达式

    -  shared_ptr  消除了显式delete调用, 但是 shared_ptr 构造时需要new, 导致了代码中某种不对称性.

 #include <boost\make_shared.hpp>
template<class T, class ...Args>
shared_ptr<T> make_shared(Args && ... args);

    - smart_ptr 也提供了一个 allocate_shared() 工厂函数, 比make_shared()多一个定制的内存分配器参数.

  - 应用于标准容器

    - 将容器作为 shared_ptr的管理对象:   shared_ptr<list<T> >

    - 将 shared_ptr作为容器的元素:  vector<shared_ptr<T> >

  - 应用于桥接模式(pimpl或者 handle/body)

    - 将类的具体实现对用户隐藏,达到最小耦合, 可以不使用虚函数实现多态.

 class sample {
private:
class impl;
shared_ptr<impl> p;
public:
sample();
void print(); //提供给外界的接口
};
class sample::impl {
public:
void print() {
cout << "impl print" << endl;
}
};
sample::sample():p(new impl){}
void sample::print() {
p->print(); //调用内部类的impl 实现print.
}
sample s;
s.print(); //实现桥接模式

  - 应用于工厂模式(前面的 make_shared() 函数也算)

 class abstract {
public:
virtual void f() = ;
virtual void g() = ;
protected:
virtual ~abstract(){} //定义为保护的,只允许自己和子类对象调用.其他任何对象无权调用delete删除.
};
class impl :public abstract{
public:
virtual void f() {
cout << "class impl f" << endl;
}
virtual void g() {
cout << "class impl g" << endl;
}
};
shared_ptr<abstract> create() {
return shared_ptr<abstract>(new impl);
}
int main(){
shared_ptr<abstract> p = create();
p->f();
p->g();
return ;
}
/* 结果:
class impl f
class impl g
*/

  - 定制删除器

    - 可以用来自动释放数据库连接, 关闭文件资源等.

 class socket_t{};
socket_t * open_socket() {
cout << "open socket" << endl;
return new socket_t;
}
void close_socket(socket_t * s) {
cout << "close socket" << endl;
}
int main(){
socket_t * s = open_socket();
shared_ptr<socket_t> p(s, close_socket); // 等价: shared_ptr<socket_t> p(s,&close_socket);
return ;
}//离开作用域时, p为调用定制的删除器 close_socket()

    - 对C语言文件操作管理就很简单了:  shared_ptr<FILE> fp(fopen("./1.txt", "r"), fclose());

  -  shared_ptr<void>

    - 优点: 能存储 void * 的指针, 而 void*  可以指向任意类型, 从而变成泛型的指针容器.

    - 缺点: 丧失了原来的类型信息, 为了需要的时候正确使用, 需要用 static_pointer_cast<T> 转换. 转换会使代码不够安全, 建议不这样用.

 /*算是删除器的高级用法了吧*/
void any_func(void * p) {
cout << "some operate" << endl;
}
int main(){
shared_ptr<void> p((void*), any_func); //容纳空指针,定制删除器, 实现退出作用域时调用任意函数.
return ;//退出作用域时执行any_fuc()
}
/*结果
some operate
*/

  - 其他: 包装成员函数, 延时释放

    - 以后有空再研究

weak_ptr类摘要

 template<class T> class weak_ptr {
public:
template<class Y> weak_ptr(shared_ptr<Y> const & r);
weak_ptr(weak_ptr const & r);
~weak_ptr(); weak_ptr & operator = (weak_ptr const & r); long use_count() const;//获取观测资源的引用计数
bool expired() const; //相当于use_count() == 0 , 但是更快
shared_ptr<T> lock() const; // 从被观测的share_ptr获取一个可用的shared_ptr对象, 从而操作资源 void reset();
void swap(weak_ptr<T> & b);
};

1. weak_ptr  的特点

  - 被设计为与 shared_ptr 共同工作, 可以从一个 shared_ptr  或者另一个 weak_ptr  对象构造获取资源的观测权.

  - 不共享(引用)资源, 不能直接操作资源, 构造/析构不会改变观测资源的引用计数.

  - 没有重载 * 和 -> , 不能像操作指针一样操作它.

2.weak_ptr 用法

  - 基本用法

 int main(){
shared_ptr<int> sp(new int());
cout << sp.use_count() << endl;
weak_ptr<int> wp(sp);
cout << wp.use_count() << endl;
if (!wp.expired()) {
shared_ptr<int> sp2 = wp.lock();
*sp2 = ;
cout << wp.use_count() << endl;
}
cout << wp.use_count() << endl;
sp.reset();
cout << wp.expired() << endl;
cout << !wp.lock() << endl;
return ;
}
/*结果
1
1
2
1
1
1
*/

  - 获得this的 shared_ptr

    -  weak_ptr 获取this指针的 shared_ptr , 使对象能获取shared_ptr实现自我管理. (使用lock() )

    - 已经被通用实现, 在 <boost/enable_shared_from_this.hpp> 内的助手类:  enable_shared_from_this<T> .

 class self_shared :public enable_shared_from_this<self_shared> {
public:
int x;
self_shared(int n) :x(n) {}
void print() {
cout << "self_shared:" << x << endl;
}
};
int main(){
shared_ptr<self_shared> sp = make_shared<self_shared>();
sp->print();
shared_ptr<self_shared> p = sp->shared_from_this();
p->x = ;
p->print();
return ;
}
/*结果
self_shared:314
self_shared:100
*/

    - 注意不能从一个普通对象(非shared_ptr)使用 shared_from_this()  来获取shared_ptr.

 //语法正确, 但是会在shared_ptr析构是企图删除一个栈上分配的对象, 发生未定义行为
self_shared ss;
shared_ptr<self_shared> p = ss.shared_from_this();

  


-->

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. sublimetext3中保存代码片段

    在日常的开发工作中,不断重复上一次敲过的代码,有时确实感到伐木累."蓝瘦"(难受)."香菇"(想哭),大概表达的也是这样的心境吧!:grinning: 所以,在 ...

  3. Code Snippets 代码片段

    Code Snippets 代码片段       1.Title : 代码片段的标题 2.Summary : 代码片段的描述文字 3.Platform : 可以使用代码片段的平台,有IOS/OS X/ ...

  4. 10个 jQuery 代码片段,可以帮你快速开发。

    转载自:http://mp.weixin.qq.com/s/mMstI10vqwu8PvUwlLborw 1.返回顶部按钮 你可以利用 animate 和 scrollTop 来实现返回顶部的动画,而 ...

  5. 代码片段添加智能提示,打造一款人见人爱的ORM框架

    SqlSugar ORM优点: 1.高性能,达到原生最高水准,比SqlHelper性能要高,比Dapper快30% 比EF快50% 2.支持多种数据库 ,sql版本更新最快,其它会定期更新,可以在多种 ...

  6. js/jquery/html前端开发常用到代码片段

    1.IE条件注释 条件注释简介 IE中的条件注释(Conditional comments)对IE的版本和IE非IE有优秀的区分能力,是WEB设计中常用的hack方法.条件注释只能用于IE5以上,IE ...

  7. Visual Studio 如何使用代码片段Code Snippet提高编程速度!!!

      使用Code Snippet简化Coding 在开发的项目的时候,你是否经常遇到需要重复编写一些类似的代码,比如是否经常会使用 for.foreach ? 在编写这两个循环语句的时候,你是一个字符 ...

  8. Visual Studio 的代码片段工具

    当安装完Visual Studio之后,会有附带一些原生的代码片段文件(*.snippet),对于vs2013参考目录如下: X:\Program Files (x86)\Microsoft Visu ...

  9. sublime代码片段

    创建方法:Tools > New Snippet 这时你会看到如下示例代码: <snippet>      <content><![CDATA[ Hello, ${ ...

随机推荐

  1. 关于adb devices连不上手机的几种情况

    启动adb 1.打开cmd首次使用adb devices,出现下面这两句,就是正在启动adb服务 C:\Users\admin>adb devices List of devices attac ...

  2. WebStorm ES6 语法支持设置

    ECMAScript 6是JavaScript语言的下一代标准,已经在2015年6月正式发布了.Mozilla公司将在这个标准的基础上,推出JavaScript 2.0.ES6的目标,是使得JavaS ...

  3. javascript数组的申明方式以及常用方法

    数组的定义: 方法1. var mycars=new Array()mycars[0]="Saab"mycars[1]="Volvo"mycars[2]=&qu ...

  4. 【学习笔记】Markdown入门

    Markdown入门 最近把博客园的编辑器换成了Markdown.   语法入门 Markdown确实好用,本来我想总结一下常用Markdown的语法,但有下面这篇文章在,我实在是不敢画蛇添足了. 基 ...

  5. mongodb的安装(linux下)

    1.去官网下载安装包 2.解压tar包 tar -zxvf filename 3.移动路径,并进入路径 mv mongodb-linux-x86_64-3.0.6/ /usr/local/mongod ...

  6. 监控服务器所有用户的操作记录(测试只记录root用户)

    在linux系统的环境下,不管是root用户还是其它的用户只有登陆系统后用进入操作我们都可以通过命令history来查看历史记录,可是假如一台服务器多人登陆,一天因为某人误操作了删除了重要的数据.这时 ...

  7. form中input是类型有哪些?

    text:文本框 password:密框码 radio:单选按钮 checkbox:复选框 file:文件选择域 hidden:隐藏域 button:按钮 reset:重置按钮 submit:表单提交 ...

  8. 大端模式、小端模式和C#反转

    A.C#大端模式和小端模式. 小端(little-endian)模式:低地址上存放低字节,高地址上存放高字节. 如0x11223344→ byte[] numBytes = new byte[]{ 0 ...

  9. RSA_JS_PHP加密解密

    root@DESKTOP-I4OIMJC /cygdrive/e/html/RSA_JS_PHP/openssl/bin # ./openssl.exe OpenSSL> genrsa -out ...

  10. SVN 提交、更新、解决冲突等操作步骤

    1. 纳入版本控制 ①新建文件abc.txt ②在文件上点右键 ③添加后文件图标发生变化 2. 提交 ①使用TortoiseSVN可以提交具体某一个文件,或某一个目录下的所有改变.方法就是在想要提交的 ...