shared_ptr

参考《boost程序库完全开发指南》

//func_eg.h

//定义了所有的示例函数

#pragma once
#include<iostream>
#include<boost\smart_ptr.hpp>
#include<vector>
using namespace boost;

void eg();
void eg1();
void eg2();
void eg3();
void eg4();
void eg_make_shared();
void eg5();
void eg_shared_array();
void eg_weak_ptr();
void eg_shared_from_this();
//shared_ptr.cpp

//示例shared_ptr的构造函数

#include"func_eg.h"
/*
	shared_ptr同样用于管理new动态分配内存对象的指针,重载了*和->操作符模仿指针操作。
	shared_ptr与scoped_ptr不同的是shared_ptr可以被共享,有正常的拷贝,赋值语义,也可以进行shared_ptr之间的比较
	shared_ptr的构造函数:
	1.无参的shared_ptr创建一个持有空指针的shared_ptr
	2.shared_ptr(Y * p)获得指向类型T的指针p的管理权,同时引用计数置为1.这个构造函数要求Y类型必须能转换为T类型。
	3.shared_ptr(shared_ptr const &r)从另外一个shared_ptr指针获得指针的管理权,同时atuo_ptr失去管理权
	4.operator=可以从另一个shared_ptr或auto_ptr获得指针的管理权
	5.shared_ptr(Y * p,D d)行为类似shared_ptr(Y * p),但使用参数d指定了析构时的定制删除器。

	shared_ptr的reset()函数作用是将引用计数减一,停止对指针的共享,除非引用计数为0,否则不会发生删除操作。
	带参数的reset()函数原指针引用计数减一,同时改为管理另一个指针

	unique()函数若当前shared_ptr是指针的唯一所有者时返回true,use_count返回指针的引用计数

	两个shared_ptr可以进行比较,比较的结果是由两个shared_ptr保存的内部指针a和b决定的,相当于a.get() == b.get()
	shared_ptr还可以使用<比较大小,同样基于内部保存的指针,但不提供<以外的比较操作符,这使得shared_ptr可以被用于标准关联容器
	typedef shared_ptr<string> sp_t;
	map<sp_t,int> m;                 //标准映射容器
	sp_t sp(new string("one"));
	m[sp] = 111;                     //关联数组用法

	在编写基于虚函数的多态代码时指针的类型转换很有用,比如把一个基类的指针转换成子类指针或者反过来,
	但对于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
	shared_ptr<std::exception> sp1(new bad_exception("error"));
	shared_ptr<std::bad_exception> sp2 = dynamic_pointer_cast<bad_exception>(sp1);
	shared_ptr<std::exception> sp3 = static_pointer_case<std::exception>(sp2);

	此外,shared_ptr还支持operator<<,输出内部的指针值
*/

//用法一
void eg(){
	shared_ptr<int> sp1(new int);    //构造函数2 
	assert(sp1.unique());

	shared_ptr<int> sp2 = sp1;       //构造函数3,第二个shared_ptr,拷贝构造函数,两个shared_ptr指向一个对象,引用计数为2
	assert(sp1 == sp2 && sp1.use_count() == 2);

	shared_ptr<int> sp3(sp1);
	std::cout << "sp3's use count:" << sp3.use_count() << std::endl;

	*sp2 = 10;                       //使用解引用操作符修改被指对象
	assert(*sp1 == 10);              //另一个shared_ptr同时被修改

	/*
	shared_ptr的reset()函数作用是将引用计数减一,停止对指针的共享,除非引用计数为0,否则不会发生删除操作。
	带参数的reset()函数原指针引用计数减一,同时改为管理另一个指针
	*/
	sp1.reset();                     //停止shared_ptr的使用
	assert(!sp1);                    //sp1不再持有任何指针

}

//shared_ptr1.cpp

//示例了shared_ptr的构造函数用法

#include"func_eg.h"
class shared {
private:
	std::shared_ptr<int> p;
public:
	shared(std::shared_ptr<int> p_) :p(p_) {}           //构造函数初始化shared_ptr
	void print() {
		std::cout << "count:" << p.use_count() << ",value = " << *p << std::endl;
	}
};
void print_func(std::shared_ptr<int> p) {
	std::cout << "count:" << p.use_count() << ",value = " << *p << std::endl;
}
void eg1() {
	std::shared_ptr<int> p(new int(20));   
	shared p1(p), p2(p);       //3.shared_ptr(shared_ptr const &r)从另外一个shared_ptr指针获得指针的管理权,同时atuo_ptr失去管理权

	p1.print();          //count:3,value = 20;
	p2.print();          //count:3,value = 20;

	*p = 30;
	print_func(p);       //count:4,value = 30;在print_func内部拷贝了一个shared_ptr对象,因此引用计数加一,函数退出时自动析构

	p1.print();          //count:3,value = 30;
}

//shared_ptr2.cpp

//示例shared_ptr用于标准容器

#include"func_eg.h"
/*
将shared_ptr应用于标准容器:
一、将容器作为shared_ptr的管理对象,如shared_ptr<list<T>>,使容器可以被安全的共享,用法与普通的shared_ptr没有区别
二、将shared_ptr作为容器的元素,如vector<shared_ptr<T>>,因为shared_ptr支持拷贝语义和比较操作,符合标准容器对元素的要求
*/

void eg2() {
	typedef std::vector<std::shared_ptr<int>> vs;              //一个持有shared_ptr的标准容器类型
	vs v(10);                                             //声明一个有10个元素的容器,元素被初始化为空指针

	int i = 0;
	for (vs::iterator pos = v.begin(); pos != v.end(); ++pos) {
		(*pos) = std::make_shared<int>(++i);          //使用工厂函数赋值
		std::cout << *(*pos) << ",";             //输出值,容器存储的是shared_ptr,所以*pos是shared_ptr类型,然后*shared_ptr才是值
	}
	std::cout << std::endl;

	std::shared_ptr<int> p = v[9];
	*p = 100;
	std::cout << std::endl << "count:" << p.use_count() << std::endl;

	for (vs::iterator pos = v.begin(); pos != v.end(); ++pos) {
		std::cout << *(*pos) << ",";             //输出值
	}

}

//shared_ptr3.cpp

//示例了工厂模式创建shared_ptr对象

#include"func_eg.h"
/*应用于工厂模式*/
/*
	工厂模式是一种创建型设计模式,这个模式包装了new操作符,使对象的创建工作集中在
	工厂类或者工厂函数中
	从而更容易适应变化,make_shared就是工厂模式的一个例子
*/
class abstrac {
public:
	virtual void f() = 0;
	virtual void g() = 0;
protected:
	~abstrac() {}              //析构函数设为受保护成员,说明除了类和它的子类,其余的类无法删除该类对象
};
class imp1 :public abstrac {
	virtual void f() { std::cout << "imp1 f" << std::endl;}
	virtual void g() { std::cout << "imp1 g" << std::endl; }
	
};
/*工厂模式返回指向分配内存产生的对象的指针,返回一个shared_ptr类型指针可以方便内存管理*/
std::shared_ptr<abstrac> create() {
	return std::shared_ptr<abstrac>(new imp1);
}

void eg4() {
	std::shared_ptr<abstrac> p = create();     //创建对象的时候,不用直接显示调用new操作符,而是调用了用户自定义的创建函数
	p->f();
	p->g();
}
//make_shared.cpp

//示例了make_shared构造shared_ptr的方法

#include"func_eg.h"

/*
shared_ptr消除了显示的delete调用,但是shared_ptr的构造还要调用new函数,使用工厂模式来解决
template<class T,class....Args>
shared_ptr<T> make_shared(...)
make_shared()最多可以接受10个参数,然后把它们传递给类型T的构造函数,创建一个shared_ptr<T>对象并放回。
*/
void eg_make_shared() {
	std::shared_ptr<std::string> sp =
		std::make_shared<std::string>("make_shared");      //string的构造函数接受一个参数,因此括号中只有一个参数
	std::shared_ptr<std::vector<int> > spv =
		std::make_shared<std::vector<int>>(10, 2);         //vector的构造函数可以接受两个参数,因此括号中可以有两个参数

	std::cout << sp.use_count() << " " << *sp << std::endl;
	std::cout << spv.use_count() << std::endl;
	for (std::vector<int>::iterator i = spv->begin(); i != spv->end(); ++i) {
		std::cout << *i;
	}
	std::cout << std::endl;
}

//shared_ptr5.cpp

//示例的定制删除器的用法

//因为shared_ptr能够存储void*类型的指针,而void*类型又可以指向任意类型,因此shared_ptr就像一个泛型的指针容器

#include"func_eg.h"
/*定制删除器*/
/*
	shared_ptr(Y * p,D d);第一个参数是要被管理的指针,第二个参数d则告诉shared_ptr在析构时不是使用delete来操作指针p
	而要用d来操作,即把delete(p)换成d(p)。
	d可以是一个函数对象,也可以是一个函数指针。
	对删除器的要求是能拷贝,不发出异常。
	为了配合删除器工作,shared_ptr提供一个自由函数get_deletee(shared_ptr<T> & p),它能够返回指向删除器的指针
	有了删除器的概念,可以用shared_ptr实现管理任意资源,只要这种资源提供了自己的释放操作,shared_ptr就能保证自动释放
*/

int * create(int k) {
	std::cout << "创建" << k << std::endl;
	int * t = new int(k);
	return t;
}
void del(int *p) {                 //删除函数的参数是指向要操作的对象的指针
	std::cout << "删除" << *p; 
}
void eg5() {
	int *p = 
	create(2);
	std::shared_ptr<int> p1(p,del);
}







你可能感兴趣的:(shared_ptr,boost)