auto_ptr它是C++标准库(<utility>)为了一个智能指针类模板来解决资源泄漏所提供的问题(注意:这只是一个简单的智能指针)

auto_ptr在事实原则的实现RAII,对资源的访问,在施工时间。释放资源时,析构函数,而相关的指针操作超载。使用起来就像普通的指针。

std::auto_ptr<ClassA> pa(new ClassA);

非常多人听说过标准auto_ptr智能指针机制,但并非每一个人都天天使用它。这真是个遗憾。由于auto_ptr优雅地攻克了C++设计和编码中常见的问题,正确地使用它能够生成健壮的代码。本文阐述了怎样正确运用auto_ptr来让你的代码更加安全——以及怎样避免对auto_ptr危急但常见的误用,这些误用会引发间断性发作、难以诊断的bug。



1.为什么称它为“自己主动”指针?

auto_ptr仅仅是众多可能的智能指针之中的一个。很多商业库提供了更复杂的智能指针。用途广泛而令人惊异,从管理引用的数量到提供先进的代理服务。能够把标准C++ auto_ptr看作智能指针的Ford Escort(elmar注:可能指福特的一种适合家居的车型):一个简易、通用的智能指针,它不包括全部的小技巧。不像专用的或高性能的智能指针那么奢华。可是它能够非常好的完毕很多普遍的工作,它非常适合日常性的使用。



auto_ptr所做的事情,就是动态分配对象以及当对象不再须要时自己主动运行清理。这里是一个简单的代码演示样例,没有使用auto_ptr所以不安全:

    // 演示样例 1(a): 原始代码

    //

    void f()

    {

      T* pt( new T );





      /*...很多其它的代码...*/





      delete pt;

    }





我们大多数人每天写类似的代码。

假设f()函数仅仅有三行而且不会有不论什么意外,这么做可能挺好的。

可是假设f()从不运行delete语句。或者是因为过早的返回。或者是因为运行函数体时抛出了异常,那么这个被分配的对象就没有被删除。从而我们产生了一个经典的内存泄漏。





能让演示样例1(a)安全的简单办法是把指针封装在一个“智能的”类似于指针的对象里,这个对象拥有这个指针而且能在析构时自己主动删除这个指针所指的对象。由于这个智能指针能够简单的当成一个自己主动的对象(这就是说,它出了作用域时会自己主动毁灭)。所以非常自然的把它称之为“智能”指针:





    // 演示样例 1(b): 安全代码, 使用了auto_ptr

    //

    void f()

    {

      auto_ptr<T> pt( new T );





      /*...很多其它的代码...*/





    } // 酷: 当pt出了作用域时析构函数被调用。

      // 从而对象被自己主动删除





如今代码不会泄漏T类型的对象。无论这个函数是正常退出还是抛出了异常。由于pt的析构函数总是会在出栈时被调用。清理会自己主动进行。





最后,使用一个auto_ptr就像使用一个内建的指针一样easy。并且假设想要“撤销”资源,又一次採用手动的全部权,我们仅仅要调用release():





    // 演示样例 2: 使用一个 auto_ptr

    //

    void g()

    {

      T* pt1 = new T;

      // 如今。我们有了一个分配好的对象





      // 将全部权传给了一个auto_ptr对象

      auto_ptr<T> pt2( pt1 );





      // 使用auto_ptr就像我们曾经使用简单指针一样

      *pt2 = 12;       // 就像 "*pt1 = 12;"

      pt2->SomeFunc(); // 就像 "pt1->SomeFunc();"





      // 用get()来获得指针的值

      assert( pt1 == pt2.get() );





      // 用release()来撤销全部权

      T* pt3 = pt2.release();





      // 自己删除这个对象,由于如今

      // 没有不论什么auto_ptr拥有这个对象

      delete pt3;





    } // pt2不再拥有不论什么指针,所以不要

      // 试图删除它...ok。不要反复删除





最后,我们能够使用auto_ptr的reset()函数来重置auto_ptr使之拥有还有一个对象。假设这个auto_ptr已经拥有了一个对象。那么,它会先删除已经拥有的对象,因此调用reset()就如同销毁这个auto_ptr,然后新建一个并拥有一个新对象:





    // 演示样例 3: 使用reset()

    //

    void h()

    {

      auto_ptr<T> pt( new T(1) );





      pt.reset( new T(2) );

        // 删除由"new T(1)"分配出来的第一个T





    } // 最后。pt出了作用域。

      // 第二个T也被删除了

2. 以下主要分析一下auto_ptr的几个要注意的地方:



1,Transfer of Ownership



auto_ptr与boost库中的share_ptr不同的,auto_ptr没有考虑引用计数,因此一个对象仅仅能由一个auto_ptr所拥有,在给其它auto_ptr赋值的时候,会转移这样的拥有关系。

#include <utility>
#include <iostream>
using namespace std; class A
{
public:
A() { id = ++count; cout << "create A" << id << "\n"; }
~A() { cout << "destroy A" << id << "\n"; }
private:
static int count;
int id;
}; int A::count = 0; /*调用该函数会丢失掉全部权*/
void sink(auto_ptr<A> a)
{
cout << "Enter sink()\n";
} /*调用该函数会创建对象,并获取全部权*/
auto_ptr<A> create()
{
cout << "Enter create()\n";
auto_ptr<A> a(new A());
return a;
} int main(int argc, char *argv[])
{
auto_ptr<A> a1 = create();
auto_ptr<A> a2 = a1; /*转移全部权,此时a1无效了*/
auto_ptr<A> a3(new A());
cout << "Exit create()\n";
sink(a2);/*丢失全部权,会发现a2的释放在sink函数中进行*/
cout << "Exit sink()\n";
return 0;
}

输出结果是:<br>Enter create()<br>create A1<br>create A2<br>Exit create()<br>Enter sink()<br>destroy A1<br>Exit sink()<br>destroy A2<br><br>

2。从上可知因为在赋值。參数传递的时候会转移全部权,因此不要轻易进行此类操作。





   比方:std::auto_ptr<ClassA> pa(new ClassA());





   bad_print(pa); //丢失了全部权





   pa->...; //Error

怎样防止函数调用转移全部权呢?

在《the c++ standard library》page43里有提到,採用const  reference,这样形參不会交出全部权。由于无法令 const reference交出全部权!!

3,使用auto_ptr作为成员变量,以避免资源泄漏。





   为了防止资源泄漏。我们通常在构造函数中申请,析构函数中释放。可是仅仅有构造函数调用成功,析构函数才会被调用,换句话说,假设在构造函数中产生了异常,那么析构函数将不会调用。这样就会造成资源泄漏的隐患。

比方,假设该类有2个成员变量,指向两个资源。在构造函数中申请资源A成功,但申请资源B失败,则构造函数失败。那么析构函数不会被调用。那么资源A则泄漏。

为了解决问题,我们能够利用auto_ptr代替普通指针作为成员变量,这样首先调用成功的成员变量的构造函数肯定会调用其析构函数,那么就能够避免资源泄漏问题。





4,不要误用auto_ptr





  1)auto_ptr不能共享全部权,即不要让两个auto_ptr指向同一个对象。

2)auto_ptr不能指向数组。由于auto_ptr在析构的时候仅仅是调用delete,而数组应该要调用delete[]。

3)auto_ptr仅仅是一种简单的智能指针。如有特殊需求。须要使用其它智能指针,比方share_ptr。

4)auto_ptr不能作为容器对象,STL容器中的元素常常要支持拷贝。赋值等操作,在这过程中auto_ptr会传递全部权。那么source与sink元素之间就不等价了。

參考:

http://www.cnblogs.com/qytan36/archive/2010/06/28/1766555.html

http://blog.csdn.net/cyblueboy83/article/details/1792463

3 c++ primer page591~

版权声明:本文博客原创文章,博客,未经同意,不得转载。

C++安全异常std:auto_ptr的更多相关文章

  1. [3] 智能指针std::auto_ptr

    [1]std::auto_ptr 对于编译器来说,智能指针实质是一个栈对象,而并非指针类型. 智能指针通过构造函数获取堆内存的管理所有权,而在其生命期结束时,再通过析构函数释放由它所管理的堆内存. 所 ...

  2. std::auto_ptr

    auto_ptr是C++标准库中(<utility>)为了解决资源泄漏的问题提供的一个智能指针类模板(注意:这只是一种简单的智能指针) auto_ptr的实现原理其实就是RAII,在构造的 ...

  3. 智能指针剖析(上)std::auto_ptr与boost::scoped_ptr

    1. 引入 C++语言中的动态内存分配没有自动回收机制,动态开辟的空间需要用户自己来维护,在出函数作用域或者程序正常退出前必须释放掉. 即程序员每次 new 出来的内存都要手动 delete,否则会造 ...

  4. C++智能指针剖析(上)std::auto_ptr与boost::scoped_ptr

    1. 引入 C++语言中的动态内存分配没有自动回收机制,动态开辟的空间需要用户自己来维护,在出函数作用域或者程序正常退出前必须释放掉. 即程序员每次 new 出来的内存都要手动 delete,否则会造 ...

  5. 关于std:auto_ptr std:shared_ptr std:unique_ptr

    很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生成健壮的代码.本文阐述了如何正确 ...

  6. Boost scoped_ptr scoped_array 以及scoped_ptr与std::auto_ptr对比

    boost::scoped_ptr和std::auto_ptr非常类似,是一个简单的智能指针,它能够保证在离开作用域后对象被自动释放.下列代码演示了该指针的基本应用: #include <str ...

  7. C++ 智能指针 std::auto_ptr 分析

    背景介绍: RAll机制 定义一个类来封装资源的分配和释放,在构造函数中完成资源的分配和初始化,在析构函数中完成资源的清理,从而保证资源的正确初始化和清理 ps:智能指针就是RAll机制的一种应用,智 ...

  8. Microsoft C++ 异常: std::system_error std::thread

    第一次使用std::thread,把之前项目里面的Windows的thread进行了替换,程序退出的然后发生了std::system_error. 经过调试,发现std::thread ,join了两 ...

  9. 关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记.

    说明 为何要写这篇文章 ,之前看过阿二的梦想船的<Poco::TCPServer框架解析> http://www.cppblog.com/richbirdandy/archive/2010 ...

随机推荐

  1. 问题:CListCtrl如何高亮选中一行 http://zhidao.baidu.com/question/100664911.html 扩展:单行、双行及完成状态的字体等等。。。

    http://zhidao.baidu.com/link?url=BKp05mfOdKbEBh21svQelpVhYjzDkIpYUZay8_3ZLSndTQn5kK0eTwQG8jBvYnwh8US ...

  2. Kinect for Xbox one(v2) + Ubuntu 14.04 +ROS 安装

    相比于kinect for xbox 360(v1)通过结构光来获取深度,Kinect for Xbox one(v2) 采用time flight技术,极大改善了深度图像的性能. kinect fo ...

  3. java根据xml配置文件导出excel通用方法

    java web项目中时常会用到导出功能,而导出excel几乎是每个项目必备的功能之一.针对形形色色的导出方法及个人平时的工作经验,特将导出excel方法整理成通用的方法,根据xml配置来实现特定的导 ...

  4. php面试题10(复习)

    php面试题10(复习) 一.总结 复习 二.php面试题10 21.谈谈 asp,php,jsp 的优缺点(1 分)(asp要钱,jsp学习成本大)答:ASP 全名 Active Server Pa ...

  5. git 分支建立及合并

    分支的新建与合并 让我们来看一个简单的分支新建与分支合并的例子,实际工作中你可能会用到类似的工作流. 你将经历如下步骤: 开发某个网站. 为实现某个新的需求,创建一个分支. 在这个分支上开展工作. 正 ...

  6. <Linux> Linux下一些常用命令(个人记录)

    mount -o loop XXXX  XXX ./XXX &   后台运行 rm -rf XXX  删除文件夹 rm -rf *  删除当前目录下的所有文件 包括文件夹 ps -ef | g ...

  7. Java序列化机制中的类版本号问题

    原文地址:http://yanwushu.sinaapp.com/java_serialversionuid/ 内容简单介绍 某些实现了serializable接口的java类中会看到名称为seria ...

  8. 【hdu 1536】S-Nim

    Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s) ...

  9. erlang tcp发包速度测试

    http://blog.sina.com.cn/s/blog_96b8a1540101317m.html 这段时间我们的项目遇到广播包的一些性能问题,想起之前看到yufeng老大提到的1s广播40K包 ...

  10. css+html+js实现多级下拉和弹出菜单

    本文将使用css+html+js实现横向菜单.具有多级弹出菜单下拉. 首先我们来看看效果图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvajkwMzgy ...