C++ 智能指针

首先明确C++ 智能指针本身不是指针,而是一个类,这个类构建的时候是用指针作为参数传递进入,在使用的时候可以用起来像指针一样使用,感觉最主要的功能是完成了指针所指向原始对象的内存管理,当对象最后生命周期结束的时候,可以用来释放指针所指向原始对象所附带的内存。换句话说,就是可以只是需要new一个对象,然后在最后不需要来delete这个对象,由智能指针自己来完成这个动作。

(1) 构造函数: 这个类的构造函数接受的参数是指针,这个指针是new出来的

(2) 析构函数: 这个类的析构函数,会可能对指针指向的对象进行释放。

(3) 智能指针本身是属于栈上的对象

【Shared_ptr 功能介绍 】

(1) Manages the storage of a pointer, providing a limited garbage-collection facility, possibly sharing that management with other objects.

(2) Objects of shared_ptr types have the ability of taking ownership of a pointer and share that ownership: once they take ownership, the group of owners of a pointer become responsible for its deletion when the last one of them releases that ownership.
这里的take ownership of a pointer和share the ownership 是很关键的。

(1) 一个 shared_ptr 实体可被多个线程同时读取;
(2) 两个的 shared_ptr 实体可以被两个线程同时写入,“析构”算写操作;
(3) 如果要从多个线程读写同一个 shared_ptr 对象,那么需要加锁。
 

这里主要考虑的是boost的shared_ptr, 下面是一些参考代码

【Shared_ptr 参考代码 --- 基本操作】

(1) 简单测试 -- 构建share_ptr对象的时候,是需要new的

int main()
{
	shared_ptr<int> sp(new int(10));                //一个指向整数的shared_ptr,指向的对象是new出来的    
	assert(sp.unique());                            //现在shared_ptr是指针的唯一持有者     
	shared_ptr<int> sp2 = sp;                       //第二个shared_ptr,拷贝构造函数     
	assert(sp == sp2 && sp.use_count() == 2);       //两个shared_ptr相等,指向同一个对象,引用计数为2    
	*sp2 = 100;                                     //使用解引用操作符修改被指对象    
	assert(*sp == 100);                             //另一个shared_ptr也同时被修改     
	sp.reset();                                     //停止shared_ptr的使用    
	assert(!sp);                                    //sp不再持有任何指针(空指针)  
}

(2) 类中含有share_ptr对象

class shared           //一个拥有shared_ptr的类    
{
private:
	shared_ptr<int> p;                          //shared_ptr成员变量    
public:
	shared(shared_ptr<int> p_) :p(p_){}          //构造函数初始化shared_ptr

	void print()                                //输出shared_ptr的引用计数和指向的值        
	{
		cout << "count:" << p.use_count() << " value =" << *p << endl;
	}
};


void print_func(shared_ptr<int> p)                //使用shared_ptr作为函数参数    
{
	//同样输出shared_ptr的引用计数和指向的值        
	cout << "count:" << p.use_count() << " value =" << *p << endl;
}
int main()
{
	shared_ptr<int> p(new int(100));
	shared s1(p), s2(p);                        //构造两个自定义类         
	s1.print(); // count = 3
	s2.print(); // count = 3
	*p = 20;                                    //修改shared_ptr所指的值        
	print_func(p); // 因为多了一个形参,count = 4
	s1.print(); // 上面函数执行完了以后,形参被释放
}

 

Shared_ptr 参考代码 --- 复杂操作 --- shared-ptr用于标准容器

(1) 一种用法是将容器作为shared_ptr管理的对象,如shared_ptr<list<T> >,使容器可以被安全地共享,用法与普通shared_ptr没有区别.


(2) 另一种用法是将shared_ptr作为容器的元素,如vector<shared_ptr<T> >,因为shared_ptr支持拷贝语义和比较操作,符合标准容器对元素的要求。


标准容器对元素的要求是: 有比较和拷贝接口? 这个后续查看

标准容器不能容纳auto_ptr,这是C++标准特别规定的(读者永远也不要有这种想法)。标准容器也不能容纳scoped_ptr,因为scoped_ptr不能拷贝和赋值。
标准容器可以容纳原始指针,但这就丧失了容器的许多好处,因为标准容器无法自动管理类型为指针的元素,必须编写额外的大量代码来保证指针最终被正确删除,这通常很麻烦很难实现。

存储shared_ptr的容器与存储原始指针的容器功能几乎一样,但shared_ptr为程序员做了指针的管理工作,可以任意使用shared_ptr而不用担心资源泄漏。
 

int main()
{
	typedef vector<shared_ptr<int>> vs;    //一个持有shared_ptr的标准容器类型        
	vs v(10);                               //声明一个拥有10个元素的容器,元素被初始化为空指针         
	int i = 0;
	for (vs::iterator pos = v.begin(); pos != v.end(); ++pos)
	{
		// make_shared<T>函数: 实际就是先根据T类的构造函数,构造一个T类型的对象,然后然后这个对象的智能指针
		// Allocates and constructs an object of type T passing args to its constructor, 
		// and returns an object of type shared_ptr<T> that owns and stores a pointer to it (with a use count of 1).
		// 根据构造函数传入的参数T类型,来分配和构造T类型的对象
		// 返回一个shared_ptr<T>类型的对象,该shared_ptr对象拥有拥有指向T类型对像的指针

		(*pos) = make_shared<int>(++i);     //使用工厂函数赋值  拷贝构造          
		cout << *(*pos) << ", ";            //输出值        
	}
	cout << endl;
	shared_ptr<int> p = v[9];
	*p = 100;
	cout << *v[9] << endl; //vector用 operator[]来获得容器内元素的值
}

// 迭代器加shared_ptr
// 这段代码需要注意的是迭代器和operator[]的用法,因为容器内存储的是shared_ptr,
// 我们必须对迭代器pos使用一次解引用操作符*以获得shared_ptr,然后再对shared_ptr使用解引用操作符*才能操作真正的值。
// *(*pos)也可以直接写成**pos,但前者更清晰,后者很容易让人迷惑。
// vector的operator[]用法与迭代器类似,也需要使用*获取真正的值。

Weak_ptr 参考代码

http://blog.csdn.net/mmzsyx/article/details/8090849

(1)weak_ptr是为了配合shared_ptr而引入的一种智能指针,它更像是shared_ptr的一个助手而不是智能指针,因为它不具有普通指针的行为,没有重载operator*和->,
它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况.

(2)weak_ptr被设计为与shared_ptr共同工作,可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。

(3)weak_ptr的一个重要用途是获得this指针的shared_ptr,使对象自己能够生产shared_ptr管理自己;对象使用weak_ptr观测this指针,这并不影响引用计数,在需要的时候就调用lock()函数,返回一个符合要求的shared_ptr共外界使用.
 

int main()
{
	cout << "hello world" << endl;
	shared_ptr<int> sp(new int(10));
	assert(sp.use_count() == 1);

	//create a weak_ptr from shared_ptr, 从一个shared_ptr或者weak_ptr对象构造
	weak_ptr<int> wp(sp);

	//not increase the use count 这个weak_ptr并不增加对象的计数
	assert(sp.use_count() == 1);

	// judge wp is invalid 
	// expired() is equivalent with use_count() == 0

	if (!wp.expired())
	{
		shared_ptr<int> sp2 = wp.lock();// get a shared_ptr

		*sp2 = 100;
		assert(wp.use_count() == 2);
		cout << *sp2 << endl;
	}// out of scope, sp2 destruct automatically, use_count()--;

	assert(sp.use_count() == 1);
	cout << *sp << endl;
	sp.reset();
	assert(wp.expired());
	assert(!wp.lock());

	//cout << *wp << endl;
}

 

 

【参考文献】

1: https://stackoverflow.com/questions/106508/what-is-a-smart-pointer-and-when-should-i-use-one

A smart pointer is a class that wraps a 'raw' (or 'bare') C++ pointer, to manage the lifetime of the object being pointed to. There is no single smart pointer type, but all of them try to abstract a raw pointer in a practical way.

Smart pointers should be preferred over raw pointers. If you feel you need to use pointers (first consider if you really do), you would normally want to use a smart pointer as this can alleviate many of the problems with raw pointers, mainly forgetting to delete the object and leaking memory.

With raw pointers, the programmer has to explicitly destroy the object when it is no longer useful.

2: https://www.codeproject.com/Articles/15351/Implementing-a-simple-smart-pointer-in-c

智能指针的实现, 算是好点的,只是有个没有参数的构造函数,是不是不行,在没有传递指针的情况下也构造,那么是不是要特殊处理

2.1: https://gist.github.com/tejainece/cb872b24828491c32dbd

 

3: https://blog.csdn.net/worldwindjp/article/details/18843087

据说实现的有问题

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值