小议auto_ptr (转)

小议auto_ptr (转)[@more@]

 小议auto_ptr

 一直以来都以为auto_ptr是个易用的东西,虽然一直都
没有用过它.直到昨天,终于用了一下VC版本的auto_ptr,
结果许多行为令人费解.
 没有办法,又重新把STL参考书研究了一遍,随后把VC版
的auto_ptr源码翻来研究了一番,原来是.....

 有所得,总结了如下一些东东,望对初学者有所帮助.同
时,若有不对的地方望各位大虾多指教.
 
 详细解说见代码注解!

//auto_ptr.h

#ifndef AUTO_PTR__H__
#define AUTO_PTR__H__

//声明:
//1.以下源代码仅供学习.任何使用过程中所造成的后果与作者无关.
//2.如果您使用了,表示您接受该声明

//作者 古斌亮
//时间 2003.06.21
//eMail: Linux@163.com">kinglinux@163.com

//vc auto_ptr:仿照VC版的auto_ptr行为写的一个auto_ptr
namespace vc
{
 template
 class auto_ptr
 {
 public:
 explicit auto_ptr(T * p = NULL):_own(p!=0), _ptr(p){}
 
 public:
 auto_ptr(const auto_ptr& y): _own(y._own), //拥有权转移到目标
 _ptr(y.release()){}
 
 auto_ptr& operator=(const auto_ptr& y)
 {
 if(this!=&y)
 {
 if(_ptr!=y._ptr)//是否同一个对象
 {
 if(_own)//是否具备拥有权
 {
 delete _ptr;
 _ptr = NULL;
 }
 _own = y._own;
 }
 else if(y._own)_own = true;
 _ptr = y.release();//拥有权转移到目标
 }
 return (*this);
 }
 
 ~auto_ptr()
 {
 if(_own)//如果具备拥有权
 {
 delete _ptr;
 _ptr = NULL;
 }
 }

 public:
 T& operator*() const
 {
 return (*_ptr);
 }

 T *operator->() const
 {
 return (_ptr);
 }

 public:
 T * release() const
 {
 ((auto_ptr*)this)->_own = false;//拥有权转移到目标
 return (_ptr);
 }

 private:
 bool _own;//记录是否拥有权
 T * _ptr;//引用指针
 };
};//namespace vc


//stl auto_ptr:仿照STL版的auto_ptr行为写的一个auto_ptr
namespace stl
{
 template
 class auto_ptr
 {
 public:
 explicit auto_ptr(T * p = NULL):_ptr(p){}
 
 public:
 auto_ptr(auto_ptr& y):_ptr(y._ptr)//拥有权转移到目标
 {
 y._ptr = NULL;//释放拥有权
 }
 
 auto_ptr& operator=(const auto_ptr& y)
 {
 if(this!=&y)
 {
 if(_ptr)//释放原先拥有的对象
 {
 delete _ptr;
 _ptr = NULL;
 }

 _ptr = y._ptr;//拥有权转移到目标
 y._ptr = NULL;//释放拥有权
 }
 return (*this);
 }
 
 ~auto_ptr()
 {
 delete _ptr;//释放拥有的对象
 }

 public:
 T& operator*() const
 {
 return (*_ptr);
 }

 T *operator->() const
 {
 return (_ptr);
 }

 private:
 T * _ptr;//指向具备拥有权对象的指针
 };
};//namespace stl

//以下的一个版本是参考<程序库>>(The C++ Standard Library)
//Nicolai M.Josuttis 著 侯捷 孟岩 译  2002年9月
//一书 P222 6.8 提出的具备reference的auto_ptr的观点所做的一个版本
//ref auto_ptr:
namespace ref
{
 template
 class auto_ptr
 {
 public:
 explicit auto_ptr(T * p = NULL):_ptr(p),_count(new unsigned long(1)){}
 
 public:
 auto_ptr(auto_ptr& y):_ptr(y._ptr),_count(y.addref()){}//增加引用计数
 
 auto_ptr& operator=(auto_ptr& y)
 {
 if(this!=&y)
 {
 if(_ptr!=y._ptr)//是否同一个对象
 {
 release();//释放自己原来的拥有权,这一步
 _ptr = y._ptr;
 _count = y.addref();//增加引用计数
 }
 }
 return (*this);
 }
 
 ~auto_ptr()
 {
 release();//释放拥有权
 }

 T& operator*() const
 {
 return (*_ptr);
 }

 T *operator->() const
 {
 return (_ptr);
 }

 unsigned long * addref(void)//增加引用计数
 {
 ++(*_count);
 return (_count);
 }

 private:
 void release(void)
 {
 if(--(*_count)==0)//减少引用计数并测试引用计数是否为0
 {
 delete _ptr;
 delete _count;
 }
 _count = NULL;//释放引用计数器
 _ptr = NULL;//释放拥有权
 }

 private:
 T * _ptr;//引用对象指针
 unsigned long * _count;//引用计数器指针
 };
};//namespace ref

//以上3个版本都是仿照现在比较大众化的被普遍接受的auto_ptr行为的
//简单实现.
//在应用上,用具备引用计数的auto_ptr的是比较好的.

//对于auto_ptr的实现还有许多方法,特别是可以依据在不同的应用场合
//实现不同的版本以改变auto_ptr的行为,让它更适合于我们的应用.
//如在自己的类库中完全可以用基类来做引用计数从而实现安全
//具备引用计数的auto_ptr
//又如可以用template<>的方法为要装载的类加一个引用计数来实现
//具备引用计数的auto_ptr

//the end.

#endif //AUTO_PTR__H__

//以下是VC6下的测试程序

//dog.h

#ifndef DOG__H__
#define DOG__H__

#include
#include

//测试类
class dog
{
public:
 dog(std::string name = "NoName"):_name(name)
 {
 std::cout< }

 ~dog()
 {
 std::cout< }

public:
 void bark(void)
 {
 std::cout<<_name always bark at rose.> }

public:
 void Name(const std::string& name)
 {
 _name = name;
 }

 std::string Name(void)
 {
 return _name;
 }

private:
 std::string _name;
};

#endif //DOG__H__

//main.cpp

#include
#include

#include "auto_ptr.h"
#include "dog.h"

/////////////////////////////////////////
//test vc auto_ptr
void test_vc_fun(void)
{
 std::cout<

 vc::auto_ptr ptom(new dog("Tom"));

 {
 vc::auto_ptr pjack(ptom);
 ptom = pjack; //1.
 pjack->Name("Jack");
 pjack->bark();
 pjack->Name("Tom");
 }
 ptom->bark();//因为有1.=>successful,如果去掉1.=>error
}


/////////////////////////////////////////
//test stl auto_ptr
void test_stl_fun(void)
{
 std::cout<

 stl::auto_ptr ptom(new dog("Tom"));

 {
 stl::auto_ptr pjack(ptom);
 pjack->Name("Jack");
 pjack->bark();
 }
 //ptom->bark();//error
}

/////////////////////////////////////////
//test ref auto_ptr
void test_ref_fun(void)
{
 std::cout<

 ref::auto_ptr ptom(new dog("Tom"));

 {
 ref::auto_ptr pjack(ptom);
 pjack->Name("Jack");
 pjack->bark();
 }

 ptom->bark();//successful
}

void main(void)
{
 std::cout< test_vc_fun();
 test_stl_fun();
 test_ref_fun();
}

//the end

 


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752043/viewspace-956658/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10752043/viewspace-956658/

信奥赛csp初赛高频考点【二分查找】(详细解析) 阅读详情

相关推荐

从跳表无锁插入到元数据原子发布:现代 C++ 存储内核如何跨越物理 I/O 与 CPU 内存模型

在现代工业级 LSM-Tree 存储引擎的内核设计中,C++ 工程师对“无锁化(Lock-Free)”与“纳秒级确定性”的极致偏执,几乎被雕刻进了每一行代码里。为了抹平动态内存分配器的碎片与互斥锁竞争,我们在写入路径上采用紧凑的 Arena 内存池与无锁单写多读跳表(),将插入操作的延迟死死压制在 CPU 缓存流水线的物理极限;为了让前台点查(Point Get)彻底告别昂贵的全局锁争用与特权级上下文切换,引擎巧妙融合了线程局部缓存(

weixin_45715405的博客 26

C++——C++基础】

本文系统介绍了C++中的命名空间、输入输出、缺省参数、函数重载与引用机制。命名空间有效避免标识符冲突,通过namespace和::实现作用域隔离;C++输入输出流(cin/cout)基于std命名空间,支持自动类型识别;缺省参数需从右向左连续定义,且声明中指定默认值;函数重载通过形参差异实现多态;引用作为变量别名,无额外内存开销,广泛用于传参与返回值,提升效率,但不可改变指向,且不能返回局部变量引用。

SHARK_pssm的博客 159

小议auto_ptr

    小议auto_ptr 一直以来都以为auto_ptr是个易用的东西,虽然一直都没有用过它.直到昨天,终于用了一下VC版本的auto_ptr,结果许多行为令人费解. 没有办法,又重新把STL参考书研究了一遍,随后把VC版的auto_ptr源码翻来研究了一番,原来是..... 有所得,总结了如下一些东东,望对初学者有所帮助.同时,若有不对的地方望各位大虾多指教.  详细解说见代码注解!

野草的专栏 1189

rust_hdc:用纯 Rust 重写鸿蒙设备连接器(HDC),一颗 3MB 二进制替代整个 C++ 工具链

协议层是性能敏感 + 安全敏感的:HDC 走 TCP/USB 批量传输,分包、握手、并发会话,Tokio 异步运行时天然匹配;跨平台一致性:macOS(IOKit)、Linux(libusb)、Windows、OHOS,同一套代码一个 flag 切换目标;产出即库:Rust 生态的 crate 分发让"工具"和"库"天然合一,crates.io 发布后即用。HDC 协议不大——核心 500 行 Rust 就能说清楚——但它连接的是整个鸿蒙开发者生态的日常。

夏天的博客 161

C++】 定时器进阶:多层时间轮原理与任务迁移

单层时间轮虽然能够以较低的开销管理大量定时任务,但当任务延迟时间跨度很大时,要么需要大量槽位,要么需要额外维护轮数。多层时间轮通过将不同时间范围的任务放到不同层级中,实现类似“秒针、分针、时针”的分级管理。本文主要介绍多层时间轮为什么出现、各层如何划分、定时任务如何选择层级,以及高层任务如何逐步迁移到低层并最终执行。

qq_64148519的博客 114

【AI大模型接入SDK】Ollama API 流式增量响应

🎬 艾莉丝的简介: 1.2.2 curl 参数释义 :静默模式,屏蔽进度条、连接日志,仅输出响应内容 :指定 HTTP 请求方法为 POST :请求头,告知服务端请求体为 JSON 格式 :携带 POST 请求体 payload;bash 环境使用单引号包裹 JSON,避免 shell 解析 JSON 内部双引号 1.2.3 不同 stream 参数终端表现 :终端逐行吐出分片 JSON,模型边生成边返回数据 :阻塞等待模型全部推理完成,一次性输出完整 JSON 报文 1.3 Ollama 流式响

艾莉丝努力练剑的博客,感谢大家一直以来的对艾莉丝的支持和鼓励,uu们如果对C/C++方向感兴趣的话,可以通过艾莉丝主页的微信名片加艾莉丝的好友,和努力练剑的艾莉丝一起加油! 1019

Person p2=Person(p) 的构造过程 和 RVO

C++17 的 guaranteed copy elision 使得 Person p2 = Person(p); 仅触发一次拷贝构造函数调用,且直接在 p2 的内存位置上完成构造,无需临时对象。Person(p) 不再代表独立的临时对象,而是“构造配方”,与 p2 的初始化为同一事件。p2 的地址始终不变,无搬运、无额外析构。此行为是标准保证,非优化结果,区别于旧版中可能发生的两次构造与移动。

jimy1的博客 150

Linux的开发工具

包管理器就类似手机上的应用商店。

2401_88240248的博客 152

嵌入式学习第38天——(汇编的基本使用(加减,函数声明;异常处理))

逻辑指令:and:与逻辑 orr: 或逻辑 eor:异或逻辑 bic:按位清0。算术指令:add:加法;rsc:反向带进位减法。比较逻辑:cmp:相当于C语言里的if。数据搬移:mov:相当于C语言里的赋值。

2503_90965834的博客 175

C++进阶系列 ()】关于线程堆栈的那些事——new、delete、delete[]

文章主要讲C++中new/delete的原理,包括构造析构、异常安全、delete[]的cookie机制、placement new等。本文从“包工头”比喻切入,剖析C++中new/delete的底层原理:new包含内存分配与构造,且具备异常安全回滚;delete先析构再释放。重点讲解delete[]通过头部Cookie记录元素个数、逆序析构,误用delete会导致UB。并延伸至内存池重载、placement new及底层malloc/free调用,帮助读者掌握内存管理核心。

2501_93095927的博客 438

实现pytorch resnet18功能(二,c++ cudnn)

/输出32*32*32-----------------------显然输入也是32*32*32。, _ci(ci), _co(co), _h(h), _w(w), _jjh(juanjihe), _pad(pading) {//int stride=2,juanjihe=1时,pading=0;原因是残差块中最后一步只实现了相加,并没有实现relu,所以这个架构中,所有残差块类都跟有relu!

ganggangwawa的博客 194

Notepad++ 鸿蒙 PC 适配全记录:保留 Scintilla 内核,用 Qt 重建桌面外壳

本文介绍开源鸿蒙PC社区对Notepad++的适配实践:基于Qt for OpenHarmony,采用“真引擎、新外壳”方案,保留Scintilla与Lexilla核心能力,重构Qt Widgets桌面外壳,实现多标签编辑、语法高亮、正则搜索、批量替换等功能。项目在鸿蒙PC上完成原生编译,支持文件关联与会话复用,兼顾性能与用户体验,验证了大型C++桌面应用向鸿蒙生态迁移的可行性。

技术交流,进来交个朋友 306

C++修炼】哈希表的实现

本文系统讲解哈希表的实现原理与代码实践。首先介绍哈希的概念,说明其本质是关键字到存储位置的映射关系;随后讲解直接定址法及其适用场景。接着引入哈希表,分析哈希冲突与负载因子的权衡,并介绍除法散列法、乘法散列法和全域散列法三种哈希函数。针对哈希冲突,重点讲解开放定址法(线性探测、二次探测、双重探测)与链地址法两种解决方案,并给出完整的 C++ 代码实现,涵盖插入、扩容、查找、删除以及字符串等非整型关键字的换处理。

Meanlong_的博客 449

VSCode C/C++环境设置

本文介绍了在VSCode中配置C/C++开发环境的完整流程:通过下载MinGW-w64工具链,安装C/C++及C/C++ Runner扩展,配置tasks.json与launch.json实现编译、运行与调试。重点说明了使用快捷键(如Ctrl+Shift+B编译、F5调试)及解决中文路径导致GDB报错的方法。适合初学者快速搭建高效C/C++开发环境。

念致达的博客 149

Tera Term 鸿蒙 PC 适配全记录:用 ArkUI 与 Native C++ 重建多协议终端工作流

开源鸿蒙PC社区推出Tera Term终端模拟器适配版本,基于ArkTS/ArkUI与C++ Native分层架构,实现TCP、Telnet、SSH及串口通信功能。项目在HarmonyOS PC真机上成功验证五类核心场景:应用启动、网络连接、双向输入输出、多会话独立管理与终端渲染。通过Node-API桥接前后端,保留原生终端语义,不依赖Win32兼容层,为嵌入式与运维用户提供稳定高效的跨平台终端体验。

稻草人 6238

C++速通2

int a = 3;int b = 4;// 声明名字空间int main()int a = 1;// 1// ::表示全局作用域 2// 3// 4return 0;```一个函数使用virtual关键字修饰,就是虚函数,虚函数是函数覆盖的前提。在QtCreator中使用斜体字。```cpppublic:// 虚函数cout << "动物爱吃饭" << endl;

qq_63858767的博客 440

单元二 · 值语义与失效规则:容器的心理模型

[[The C++ Standard Library 2nd Edition-2012-英文版.pdf|STL 2nd (2012)]] §6.11.2/§7.11(值语义)、§7.2–7.3(失效表);[[C++ Move Semantics - The Complete Guide 2022 Version-2022-英文版.pdf|Move Semantics]] ch1.1.2/§4.3.6/§7.1:容器里装的到底是值还是引用?我的迭代器、引用、指针,哪一次操作之后就不能再用了?

linx295的博客 130
上一篇: 用JDOM处理XML文档 (转)
下一篇: 让基于对话框的应用程序有启动画面 (转)
csd3176
博客等级 码龄11年 20粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值