通过对VC版本的auto_ptr的源代码得知VC版本还有一点小缺陷,又对VS版本的auto_ptr做了一些剖析,具体代码和注释如下:

 //假设全局pa2都是用pa1来构造
//如:pa2(pa1)、pa2=pa1 template<class _Ty> //auto_ptr类声明
class auto_ptr; template<class _Ty>
struct auto_ptr_ref //auto_ptr的辅助类
{
explicit auto_ptr_ref(_Ty *_Right): _Ref(_Right)
{}
_Ty *_Ref;
}; template<class _Ty>
class auto_ptr//auto_ptr类
{
public:
typedef auto_ptr<_Ty> _Myt; //管理类的类型
typedef _Ty element_type; //被管理元素的类型 explicit auto_ptr(_Ty *_Ptr = ) : _Myptr(_Ptr) //构造
{} //从原始指针中获取控制权 //若pa2(pa1);
auto_ptr(_Myt& _Right) : _Myptr(_Right.release()) //拷贝构造
{} //若:pa2(pa1)
auto_ptr(auto_ptr_ref<_Ty> _Right)
{
// 用右值来构造
_Ty *_Ptr = _Right._Ref; //将pa1的指针保存在Ptr中
_Right._Ref = ; // 将pa1的指针指向空
_Myptr = _Ptr; // 将pa2的地址指向pa1的地址
} template<class _Other>
operator auto_ptr<_Other>() //转换为可转换的类型
{
return (auto_ptr<_Other>(*this));
} template<class _Other>
operator auto_ptr_ref<_Other>() //隐式类型转换,将auto_ptr类型指针转换为auto_ptr_ref类型
{
_Other *_Cvtptr = _Myptr;
auto_ptr_ref<_Other> _Ans(_Cvtptr);
_Myptr = ;
return (_Ans);
} template<class _Other>
_Myt& operator=(auto_ptr<_Other>& _Right) //针对可转换为 _Ty* 类型的 _Other* 类型的拷贝函数
{
reset(_Right.release());
return (*this);
} template<class _Other> //特定类型构造函数
auto_ptr(auto_ptr<_Other>& _Right) : _Myptr(_Right.release())
{} //针对可转换为 _Ty* 类型的 _Other* 类型的构造函数 //若:pa2=pa1
_Myt& operator=(_Myt& _Right) //拷贝赋值函数
{
reset(_Right.release());
return (*this);
} //若:pa2=pa1
_Myt& operator=(auto_ptr_ref<_Ty> _Right) //将一个 auto_ptr_ref 类型的变量赋值给 *this
{
_Ty *_Ptr = _Right._Ref; //将pa1的Ref指针赋值给pa2的_Ptr指针
_Right._Ref = ; // 将pa1的Ref指针指向空
reset(_Ptr); // 将pa2的_Myptr指向pa1
return (*this);
} ~auto_ptr() //析构
{
delete _Myptr; //析构指针所指向的内容
} _Ty& operator*() const //重载*
{
if (_Myptr == )
{
_DEBUG_ERROR("auto_ptr not dereferencable");
}
return (*get());
} _Ty *operator->() const //重载->
{
return (get());
} _Ty *get() const //用来返回_Myptr的地址
{
return (_Myptr);
} _Ty *release() //将一个对象的_Myptr记住,再指向空,然后再把其记住的地址返回
{
_Ty *_Tmp = _Myptr; //先将pa1的指针用Tmp保存,
_Myptr = ; //再讲pa1的指针指向空
return (_Tmp); // 返回Tmp即原来pa1指向的地址
} void reset(_Ty *_Ptr = ) //将this的_Myptr指向传进来的指针的地址
{
if (_Ptr != _Myptr) //如果pa1“以前的”(pa1在release()中被指向空,就是返回的那个Tmp用来记住pa1以前的那个地址)那个地址所指向的地址不等于pa2的地址
delete _Myptr; //先析构pa2所指向的地址 _Myptr = _Ptr; //再将pa2地址指向返回来的pa1的老地址
} private:
_Ty *_Myptr;
};

测试代码:

 int main(int argc, char* argv[])
{
auto_ptr<int> pa(new int());
auto_ptr<int>pa1(pa);
cout << *pa1<<endl;
auto_ptr<int> pa2;
pa2 = pa1;
cout << *pa2 << endl;
auto_ptr_ref<int> par1(new int());
auto_ptr<int> pa3(par1);
cout << *pa3 << endl;
return ;
}

运行结果:

10
10
20

auto_prt的VS版本源码剖析的更多相关文章

  1. auto_ptr的VC版本源码剖析

    auto_ptr是当前C++标准库(STL)中提供的一种智能指针,包含于头文件 #include<memory> .auto_ptr 能够方便的管理单个堆内存对象,在你不用的时候自动帮你释 ...

  2. spring各个版本源码

    各版本源码下载地址 http://maven.springframework.org/release/org/springframework/spring/

  3. Spring各版本源码下载

    spring framework 各版本源码下载地址 现在spring的源码下载地址真是不好找,这次终于找到了.记录一下,以帮助需要的朋友. https://github.com/spring-pro ...

  4. [转帖]nginx1.17.2版本源码安装

    nginx1.17.2版本源码安装 原创: 沧海书生 Ansible爱好者 昨天 公众号里面的内容 这里简单测试了下 在x86的虚拟机里面编译安装 nginx 仅make make install n ...

  5. Kafka 0.10.1版本源码 Idea编译

    Kafka 0.10.1版本源码 Idea编译 1.环境准备 Jdk 1.8 Scala 2.11.12:下载scala-2.11.12.msi并配置环境变量 Gradle 5.6.4: 下载Grad ...

  6. 任务驱动,Winform VS WEB对比式学习.NET开发系列第一篇------身份证解析(不断更新的WEB版本及Winform版本源码)

    一 本系列培训随笔适用人群 1. 软件开发初学者 2. 有志于转向Web开发的Winform程序员 3. 想了解桌面应用开发的Web程序员 二 高效学习编程的办法 1 任务驱动方式学习软件开发 大部分 ...

  7. 网站安全通用防护代码(C#版本源码提供)

    每一个开发者都会意识到,网站发布之前,需要进行安全检查. 那么如何拦截攻击者注入恶意代码?如何防御诸如跨站脚本攻击(XSS).SQL注入攻击等恶意攻击行为? 针对目前常见的一些安全问题,结合目前一些常 ...

  8. spring framework 各版本源码下载地址

    现在spring的源码下载地址真是不好找,这次终于找到了.记录一下,以帮助需要的朋友. https://github.com/spring-projects/spring-framework/tags ...

  9. jquery的2.0.3版本源码系列(6):2880-3042行,回调对象,对函数的统一管理

    目录 1 . 回调对象callbacks的演示 回调的使用有一点像事件绑定,先绑定好,等到有点击事件或者其他时就触发. <script src="js/jquery-2.0.3.js& ...

随机推荐

  1. BZOJ 2467: [中山市选2010]生成树

    有一种图形叫做五角形圈.一个五角形圈的中心有1个由n个顶点和n条边组成的圈.在中心的这个n边圈的每一条边同时也是某一个五角形的一条边,一共有n个不同的五角形.这些五角形只在五角形圈的中心的圈上有公共的 ...

  2. java中类的构造方法出错点

    大家请看下面的这个代码 package ppt_test; public class test1 { public static void main(String args[]) { Foo obj1 ...

  3. win10文件夹 无法显示当前所有者 管理员都不行

    1.在win10系统桌面上,任务栏,右键,单击任务管理器. 2.单击性能. 3.单击打开资源监视器. 4.在单击CPU标签,然后再“关联的句柄”右侧的搜索框中输入要删除的文件夹名.例:tre文件夹名. ...

  4. jmeter请求报错

    jmeter发送json数据,报405.400错误解决方案: https://www.cnblogs.com/sunny-sl/p/8044284.html 405:Content-Type不对 40 ...

  5. [Agc002E/At1999] Candy Piles - 博弈论

    有n堆石子,第i堆有ai个石子.有两种操作: 把石子最多的那一堆给丢掉 把每一堆全部丢掉一个 谁拿走最后石子谁输.判断胜负情况. 直觉转化为一个走棋盘问题 考虑如何计算左下角点的状态 找到原点最右上方 ...

  6. [P1361] 小M的作物 - 最小割

    没想到今天早上的第一题网络流就血了这么多发 从经典的二选一问题上魔改 仍然考虑最小割 #include <bits/stdc++.h> using namespace std; #defi ...

  7. nodejs使用promise实现sleep

    个人博客 地址:http://www.wenhaofan.com/article/20181120180225 let sleep = function (delay) { return new Pr ...

  8. Linux下Libevent安装和简单实用

    前言 Libevent 是一个用C语言编写的.轻量级的开源高性能事件通知库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大:源代码相 ...

  9. sql简单练习语句

    排序是每个软件工程师和开发人员都需要掌握的技能.不仅需要通过编程面试,还要对程序本身有一个全面的理解.不同的排序算法很好地展示了算法设计上如何强烈的影响程序的复杂度.运行速度和效率. 排序有很多种实现 ...

  10. vscode+vue 一些基本操作

    1.安装好 vscode 和 node.js 安装node.js是为了用npm(管理项目依赖) 2.调出终端 crtl +~ , 3.终端全局安装 vue-cli  安装整个脚手架,能快速给我们构建v ...