今天看了一下Standard C++有关auto_ptr的介绍,感觉那个结构不清晰,直接看源码

// auto_ptr implementation -*- C++ -*- // Copyright (C) 2007, 2008 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 2, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this library; see the file COPYING. If not, write to // the Free Software Foundation, 51 Franklin Street, Fifth Floor, // Boston, MA 02110-1301, USA. // As a special exception, you may use this file as part of a free software // library without restriction. Specifically, if other files instantiate // templates or use macros or inline functions from this file, or you compile // this file and link it with other files to produce an executable, this // file does not by itself cause the resulting executable to be covered by // the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by // the GNU General Public License. /** @file backward/auto_ptr.h * This is an internal header file, included by other library headers. * You should not attempt to use it directly. */ #ifndef _STL_AUTO_PTR_H #define _STL_AUTO_PTR_H 1 #include <bits/c++config.h> #include <debug/debug.h> _GLIBCXX_BEGIN_NAMESPACE(std) /** * A wrapper class to provide auto_ptr with reference semantics. * For example, an auto_ptr can be assigned (or constructed from) * the result of a function which returns an auto_ptr by value. * * All the auto_ptr_ref stuff should happen behind the scenes. */ template<typename _Tp1> struct auto_ptr_ref { _Tp1* _M_ptr; explicit auto_ptr_ref(_Tp1* __p): _M_ptr(__p) { } } _GLIBCXX_DEPRECATED_ATTR; /** * @brief A simple smart pointer providing strict ownership semantics. * * The Standard says: * <pre> * An @c auto_ptr owns the object it holds a pointer to. Copying * an @c auto_ptr copies the pointer and transfers ownership to the * destination. If more than one @c auto_ptr owns the same object * at the same time the behavior of the program is undefined. * * The uses of @c auto_ptr include providing temporary * exception-safety for dynamically allocated memory, passing * ownership of dynamically allocated memory to a function, and * returning dynamically allocated memory from a function. @c * auto_ptr does not meet the CopyConstructible and Assignable * requirements for Standard Library <a * href="tables.html#65">container</a> elements and thus * instantiating a Standard Library container with an @c auto_ptr * results in undefined behavior. * </pre> * Quoted from [20.4.5]/3. * * Good examples of what can and cannot be done with auto_ptr can * be found in the libstdc++ testsuite. * * _GLIBCXX_RESOLVE_LIB_DEFECTS * 127. auto_ptr<> conversion issues * These resolutions have all been incorporated. */ template<typename _Tp> class auto_ptr { private: _Tp* _M_ptr; public: /// The pointed-to type. typedef _Tp element_type; /** * @brief An %auto_ptr is usually constructed from a raw pointer. * @param p A pointer (defaults to NULL). * * This object now @e owns the object pointed to by @a p. */ explicit auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { } /** * @brief An %auto_ptr can be constructed from another %auto_ptr. * @param a Another %auto_ptr of the same type. * * This object now @e owns the object previously owned by @a a, * which has given up ownership. */ auto_ptr(auto_ptr& __a) throw() : _M_ptr(__a.release()) { } /** * @brief An %auto_ptr can be constructed from another %auto_ptr. * @param a Another %auto_ptr of a different but related type. * * A pointer-to-Tp1 must be convertible to a * pointer-to-Tp/element_type. * * This object now @e owns the object previously owned by @a a, * which has given up ownership. */ template<typename _Tp1> auto_ptr(auto_ptr<_Tp1>& __a) throw() : _M_ptr(__a.release()) { } /** * @brief %auto_ptr assignment operator. * @param a Another %auto_ptr of the same type. * * This object now @e owns the object previously owned by @a a, * which has given up ownership. The object that this one @e * used to own and track has been deleted. */ auto_ptr& operator=(auto_ptr& __a) throw() { reset(__a.release()); return *this; } /** * @brief %auto_ptr assignment operator. * @param a Another %auto_ptr of a different but related type. * * A pointer-to-Tp1 must be convertible to a pointer-to-Tp/element_type. * * This object now @e owns the object previously owned by @a a, * which has given up ownership. The object that this one @e * used to own and track has been deleted. */ template<typename _Tp1> auto_ptr& operator=(auto_ptr<_Tp1>& __a) throw() { reset(__a.release()); return *this; } /** * When the %auto_ptr goes out of scope, the object it owns is * deleted. If it no longer owns anything (i.e., @c get() is * @c NULL), then this has no effect. * * The C++ standard says there is supposed to be an empty throw * specification here, but omitting it is standard conforming. Its * presence can be detected only if _Tp::~_Tp() throws, but this is * prohibited. [17.4.3.6]/2 */ ~auto_ptr() { delete _M_ptr; } /** * @brief Smart pointer dereferencing. * * If this %auto_ptr no longer owns anything, then this * operation will crash. (For a smart pointer, "no longer owns * anything" is the same as being a null pointer, and you know * what happens when you dereference one of those...) */ element_type& operator*() const throw() { _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0); return *_M_ptr; } /** * @brief Smart pointer dereferencing. * * This returns the pointer itself, which the language then will * automatically cause to be dereferenced. */ element_type* operator->() const throw() { _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0); return _M_ptr; } /** * @brief Bypassing the smart pointer. * @return The raw pointer being managed. * * You can get a copy of the pointer that this object owns, for * situations such as passing to a function which only accepts * a raw pointer. * * @note This %auto_ptr still owns the memory. */ element_type* get() const throw() { return _M_ptr; } /** * @brief Bypassing the smart pointer. * @return The raw pointer being managed. * * You can get a copy of the pointer that this object owns, for * situations such as passing to a function which only accepts * a raw pointer. * * @note This %auto_ptr no longer owns the memory. When this object * goes out of scope, nothing will happen. */ element_type* release() throw() { element_type* __tmp = _M_ptr; _M_ptr = 0; return __tmp; } /** * @brief Forcibly deletes the managed object. * @param p A pointer (defaults to NULL). * * This object now @e owns the object pointed to by @a p. The * previous object has been deleted. */ void reset(element_type* __p = 0) throw() { if (__p != _M_ptr) { delete _M_ptr; _M_ptr = __p; } } /** * @brief Automatic conversions * * These operations convert an %auto_ptr into and from an auto_ptr_ref * automatically as needed. This allows constructs such as * @code * auto_ptr<Derived> func_returning_auto_ptr(.....); * ... * auto_ptr<Base> ptr = func_returning_auto_ptr(.....); * @endcode */ auto_ptr(auto_ptr_ref<element_type> __ref) throw() : _M_ptr(__ref._M_ptr) { } auto_ptr& operator=(auto_ptr_ref<element_type> __ref) throw() { if (__ref._M_ptr != this->get()) { delete _M_ptr; _M_ptr = __ref._M_ptr; } return *this; } template<typename _Tp1> operator auto_ptr_ref<_Tp1>() throw() { return auto_ptr_ref<_Tp1>(this->release()); } template<typename _Tp1> operator auto_ptr<_Tp1>() throw() { return auto_ptr<_Tp1>(this->release()); } } _GLIBCXX_DEPRECATED_ATTR; // _GLIBCXX_RESOLVE_LIB_DEFECTS // 541. shared_ptr template assignment and void template<> class auto_ptr<void> { public: typedef void element_type; } _GLIBCXX_DEPRECATED_ATTR; _GLIBCXX_END_NAMESPACE #endif /* _STL_AUTO_PTR_H */

从代码中可以看出

1. auto_ptr可以辅助我们管理内存

2. auto_ptr在‘复制’的时候,管理权会放弃

3. auto_ptr_ref的引入 巧妙解决了右值引用的问题。

对于第3点,详细说明一下

在标准C++中 右值引用时不可以的。比如:

如果有函数 int f(void);

我们采用: int &p =f(void);这样的方式,在标准C++中是不允许的

必须要        const int &p = f(void); //之所以要说是标准C++ 因为在Vc中是支持的。呵呵

从源代码上可以看出 auto_ptr的拷贝构造函数“不是”我们常看见的 auto_ptr(const atuo_ptr<T> &p);

而是设计为 auto_ptr(atuo_ptr<T> p)这样的样式(原因是在这个拷贝构造函数中,对于传入的参数我们必须使其放弃管理权)

在这种设计下:我们就不能写这样的函数 atuo_ptr p( f(void) )

所以引入了auto_ptr_ref这个辅助结构来帮助我们的auto_ptr可以执行这样的函数 atuo_ptr p( f(void));

具体步骤为:

===============================================================================

auto_ptr<int> p(auto_ptr<int>(new int(0)))

便可以成功,过程如下:

1. 构造临时对象 auto_ptr<int>(new int(0))

2. 想将临时对象通过拷贝构造函数传给p,却发现没有合适的拷贝构造函数,因为只有auto_ptr(auto_ptr& rhs)这个不能用,又没有auto_ptr(const auto_ptr& rhs) (因为用了在所有权转移中会出错),呵呵!

3. 编译器只能曲线救国,看看类型转换后能不能传递。

4. 由于我们定义了 operator auto_ptr_ref() 所以编译器自然就可以试一下转为 auto_ptr_ref类型。

5. 编译器猛然间发现,我们定义了 auto_ptr(auto_ptr_ref rhs):ap(rhs.p){} 的构造函数,可以传递。

6. 顺利构造p,任务完成。

上面引用 http://blog.csdn.net/benny5609/archive/2008/06/06/2516822.aspx 的描述。

===============================================================================

atuo_ptr 实现相关推荐

  1. C++11使用的一些细节点

    extern "C" 在.cpp中加 extern "C",即扩展为C的编译方式,可以让编译器不采用C++的编译方式,而是采用C语言的编译方式来编译. .... ...

  2. C++软件开发面试题总结

    面试题有难有易,不能因为容易,我们就轻视,更不能因为难,我们就放弃.我们面对高薪就业的态度永远不变,那就是坚持.坚持.再坚持.出现问题,找原因:遇到困难,想办法.我们一直坚信只有在坚持中才能看到希望, ...

  3. 对象生死劫 - 构造函数和析构函数的异常

    对象生死劫 - 构造函数和析构函数的异常 2007-09-13 09:11 2086人阅读 评论(7) 收藏 举报 构造函数和析构函数分别管理对象的建立和释放,负责对象的诞生和死亡的过程.当一个对象诞 ...

  4. 对象生死劫 - 构造函数和析构函数的异常(转)

    构造函数和析构函数分别管理对象的建立和释放,负责对象的诞生和死亡的过程.当一个对象诞生时,构造函数负责创建并初始化对象的内部环境,包括分配内存.创建内部对象和打开相关的外部资源,等等.而当对象死亡时, ...

  5. 第一篇:C/C++语法与std数据结构

    系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录 前言 编程基础及进阶 一.C/C++的介绍 1.从面向过程,到面向对象 面 ...

  6. 秋招面经(后端开发)——语言篇(C++)

    其他后端所需技术栈个人总结链接汇总: 秋招面经(后端开发)--语言篇(C++) C++ STL容器底层学习(个人总结) 秋招面经(后端开发)--数据库篇(MySQL) 秋招面经(后端开发)--操作系统 ...

最新文章

  1. python 画希尔伯特曲线
  2. vorwerk 机器人_福维克(Vorwerk)--吸尘器行业的quot;安利quot;
  3. *第6章 判别分析及R使用
  4. HDOJ 1286 HDU 1286 找新朋友 ACM 1286 IN HDU
  5. “中国开发者大调查”问卷收集即将结束,快来看这次中奖“末班车”你赶上了吗?
  6. php validate验证用户,PHP validate 数据验证demo
  7. 初学UML之-------用例图
  8. YonBIP—助力企业数字化转型之道
  9. matlab2016b版本安装
  10. 映美精(IMAGINGSOURCE)相机与OPENCV库(包含工程源码)
  11. php 获取 星期几,php怎么获得星期几
  12. 交通灯控制系统(30-5-20-5)【数电课设】
  13. linux 系统命令被后门修改_一次Linux系统被攻击的分析过程
  14. P5594 【XR-4】模拟赛
  15. 科技创新创业2022年阜阳市高新企业扶持奖补政策新出申报条件材料流程
  16. 初学习数据库,记录1,在sql server数据表主键中插入UUID
  17. 斐波那契数的时间复杂度、空间复杂度详解
  18. ubuntu1804安装docker
  19. VIEWGOOD(远古)P2P流媒体直播系统的设计与实现
  20. 一种可以使身体吸收天道法则的电脑

热门文章

  1. 南京大学计算机学类,南京大学计算机专业厉害吗?
  2. 文献写作:学术研究论文
  3. python平方根_如何在Python中找到平方根?
  4. python中utf-8和gbk编码格式_python中unicode、utf8、gbk等编码问题
  5. 大数据技术架构_大数据架构流程图
  6. Switch函数的使用
  7. excel冻结行和列_Spire.Cloud.Excel 冻结或解除冻结Excel中的行和列
  8. python体测成绩数据分析_Python+Excel数据分析实战:军事体能考核成绩评定(二)基本框架和年龄计算...
  9. 同样硬件安装不同操作系统:Win7和Win10对于同一段程序源码的编译速度不同
  10. Java 不懂英语可以用拼音声明_编程经验点滴----避免使用汉语拼音做变量名