智能指针
2016-03-31 22:23
351 查看
一.为什么有智能指针?由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete。可是程序员容易忘记 delete,最终导致没有 delete,程序异常。用智能指针便可以有效缓解这类问题。
二.设计思想想法:如果ps指向的内存也被自动释放,那该有多好啊。(析构函数有这个功能。如果ps有一个析构函数,该析构函数将在ps过期时自动释放它指向的内存。但ps的问题在于,它只是一个常规指针,不是有析构凼数的类对象指针。如果它指向的是对象,则可以在对象过期时,让它的析构函数删除指向的内存。)智能指针的设计思想:将基本类型指针封装为类对象指针(这个类肯定是个模板,以适应不同基本类型的需求),并在析构函数里编写delete语句删除指针指向的内存空间。
从较浅的层面看,智能指针是利用了一种叫做RAII(资源获取即初始化)的技术对普通的指针进行封装,这使得智能指针实质是一个对象,行为表现的却像一个指针。
智能指针和普通指针的区别在于智能指针实际上是对普通指针加了一层封装机制,这样的一层封装机制的目的是为了使得智能指针可以方便的管理一个对象的生命期。
三. 多个指针指向同一个对象,会导致同一个对象被释放多次而导致错误,解决方法:定义陚值运算符,使之执行深复制。这样两个指针将指向不同的对象,其中的一个对象是另一个对象的副本,缺点是浪费空间,所以智能指针都未采用此方案。
建立所有权(ownership)概念。对于特定的对象,只能有一个智能指针可拥有,这样只有拥有对象的智能指针的构造函数会删除该对象。然后让赋值操作转让所有权。这就是用于auto_ptr和uniqiie_ptr 的策略,但unique_ptr的策略更严格。
创建智能更高的指针,跟踪引用特定对象的智能指针数。这称为引用计数。例如,赋值时,计数将加1,而指针过期时,计数将减1,。当减为0时才调用delete。这是shared_ptr采用的策略。
四. 3种智能指针:Auto_ptr、ScopedPtr、SharedPtr.(1)Auto_ptr:auto_ptr在构造时获取对某个对象的所有权,在析构时释放该对象。我们可以这样使用auto_ptr来提高代码安全性.
在拷贝构造或赋值操作时,auto_ptr的做法是“所有权转移”,即拷贝或赋值的源对象将失去对“裸”指针的所有权
与一般拷贝构造函数,赋值函数不同,auto_ptr的拷贝构造函数,赋值函数的参数为引用而不是常引用(const).
一个auto_ptr不能同时拥有两个以上的“裸”指针,所以,拷贝或赋值的目标对象应该先释放其原来所拥有的对象。
缺陷:访问交出所有权的智能指针(空指针)而导致内存崩溃问题。
(2)ScopedPtr
ScopedPtr是通过把拷贝构造或赋值操作设为私有,使外部不能调用.下面我将把它的代码实现写在下面
(3)SharedPtr
SharedPtr是利用引用计数
二.设计思想想法:如果ps指向的内存也被自动释放,那该有多好啊。(析构函数有这个功能。如果ps有一个析构函数,该析构函数将在ps过期时自动释放它指向的内存。但ps的问题在于,它只是一个常规指针,不是有析构凼数的类对象指针。如果它指向的是对象,则可以在对象过期时,让它的析构函数删除指向的内存。)智能指针的设计思想:将基本类型指针封装为类对象指针(这个类肯定是个模板,以适应不同基本类型的需求),并在析构函数里编写delete语句删除指针指向的内存空间。
从较浅的层面看,智能指针是利用了一种叫做RAII(资源获取即初始化)的技术对普通的指针进行封装,这使得智能指针实质是一个对象,行为表现的却像一个指针。
智能指针和普通指针的区别在于智能指针实际上是对普通指针加了一层封装机制,这样的一层封装机制的目的是为了使得智能指针可以方便的管理一个对象的生命期。
三. 多个指针指向同一个对象,会导致同一个对象被释放多次而导致错误,解决方法:定义陚值运算符,使之执行深复制。这样两个指针将指向不同的对象,其中的一个对象是另一个对象的副本,缺点是浪费空间,所以智能指针都未采用此方案。
建立所有权(ownership)概念。对于特定的对象,只能有一个智能指针可拥有,这样只有拥有对象的智能指针的构造函数会删除该对象。然后让赋值操作转让所有权。这就是用于auto_ptr和uniqiie_ptr 的策略,但unique_ptr的策略更严格。
创建智能更高的指针,跟踪引用特定对象的智能指针数。这称为引用计数。例如,赋值时,计数将加1,而指针过期时,计数将减1,。当减为0时才调用delete。这是shared_ptr采用的策略。
四. 3种智能指针:Auto_ptr、ScopedPtr、SharedPtr.(1)Auto_ptr:auto_ptr在构造时获取对某个对象的所有权,在析构时释放该对象。我们可以这样使用auto_ptr来提高代码安全性.
在拷贝构造或赋值操作时,auto_ptr的做法是“所有权转移”,即拷贝或赋值的源对象将失去对“裸”指针的所有权
与一般拷贝构造函数,赋值函数不同,auto_ptr的拷贝构造函数,赋值函数的参数为引用而不是常引用(const).
一个auto_ptr不能同时拥有两个以上的“裸”指针,所以,拷贝或赋值的目标对象应该先释放其原来所拥有的对象。
缺陷:访问交出所有权的智能指针(空指针)而导致内存崩溃问题。
(2)ScopedPtr
ScopedPtr是通过把拷贝构造或赋值操作设为私有,使外部不能调用.下面我将把它的代码实现写在下面
(3)SharedPtr
SharedPtr是利用引用计数
#include<iostream> using namespace std; template<class T> class ScopedPtr { public: ScopedPtr(); ScopedPtr(T* ptr); T& operator*(); //记得加& T* operator->(); ~ScopedPtr(); private: ScopedPtr<T>(const ScopedPtr<T>& sp); ScopedPtr<T>& operator=(const ScopedPtr<T>& sp); private: T* _ptr; }; template<class T> ScopedPtr<T>::ScopedPtr() :_ptr(NULL) {} template<class T> ScopedPtr<T>::ScopedPtr(T* ptr) :_ptr(ptr) {} template<class T> T& ScopedPtr<T>::operator*() //记得加& { return *_ptr; } template<class T> T* ScopedPtr<T>:: operator->() { return _ptr; } template<class T> ScopedPtr<T>::~ScopedPtr() { delete _ptr; _ptr=NULL; } void Test() { int *p1=new int[5]; ScopedPtr<int> sp1(p1); *p1=1; cout<<*sp1<<endl; } int main() { Test(); system("pause"); return 0; }参考文献:http://www.cnblogs.com/lanxuezaipiao/p/4132096.html http://www.zhihu.com/question/20368881
相关文章推荐
- 关于matplot的中文显示问题
- PHP的配置
- YII 两表间和两模块间的数据库查询
- PHP文件上传设置和处理(单文件)
- 自己写的yaf的mysql pdo扩展
- My study note of PHP language(II)
- Connect.class.php连接数据库(随时修改)
- <php>PDO用法二
- <php>PDO用法一
- <php>PDO链接方法
- 向vsftp服务器上传文件报“550 Permission denied”错误的解决办法 (2012
- 将输出流OutputStream转化为输入流InputStream的方法
- PHP 之 FastCGI 与 mod_php 详解
- PHP文件锁定机制
- get_headers函数判断远程文件是否存在
- PHP简单留言板
- php防止sql注入的自定义函数
- php中放置sql注入的几个函数
- php学习中的session和cookie的初步认识及其他
- 找不到 phpize