C++句柄类(智能指针)小结
句柄类作用主要有两个:
- 支持面向对象编程,实现多态性质;
- 减少头文件的编译依赖关系,让文件间的编译更加独立。
句柄类存储和管理基类指针,指针既可以指向基类类型对象又可以指向派生类型对象。用户通过句柄类访问继承层次的操作,用户可以获得动态行为,同时能够确保自动正确的销毁动态分配的对象,防止内存泄露。《C++ Primer》15.7节中用购物篮的例子说明了C++不能通过对象支持多态,而必须使用指针或引用。如果multiset保存基类的对象:派生类对象只有基类部分保存下来,而派生类部分被切掉;如果保存派生类的对象,基类对象无法有效转换为派生类对象。
在Effective C++类的实现中条款22说明了为了实现接口和实现的分离,将对象的实现隐藏在指针身后,这样就能减少头文件的编译依赖关系。实现技术:使用引用数(referencecount)。句柄类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。计数器变化的情况:
- 创建类的新对象时,初始化指针并将引用计数置为1;
- 对象作为另一对象的副本,拷贝构造函数拷贝指针并增加与之相应的引用计数;
- 对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;
- 调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除对象)。
一、指针型句柄
定义一个句柄类,管理继承层次中对象的指针,同时使用引用计数,自动释放相关继承类的对象。
//基类
class A{
public:... //类定义virtual A *clone() const //虚函数,复制基类对象指针{ return new A(*this); }
private:... //类定义
};
//派生类
class B : public A {
public:... //类定义B *clone() const //重写,复制派生类对象指针{ return new B(*this); }
private:... //类定义
};//句柄类,管理对象指针和引用计数
class C{
public:C() : p(0), use( new int(1)) {}// 用继承中的对象生成句柄类对象C( const A &a ) : p( a.clone()), use( new int(1)) {}//复制构造函数C( const Handle &h ) :p(h.p), use(h.use) { ++*use; } //计数加1~C() { decr_use(); }const A *operator->() const //返回对象指针{ if(p) return p; }const A &operator*() const //返回对象{ if(p) return *p; }C &operator=( const C &); //赋值
private:A *p; //对象指针int *use; //引用计数
void decr_use()
{if(--*use == 0){ delete p; delete use; }
}
};
赋值操作
C &C::operator=( const C &rhs )
{++&rhs.use; //右操作数计数加1decr_use(); //检查左操作数计数p = rhs.p; //赋值use = rhs.use;return *this;
}
句柄类的使用
A a;
C h1(a); //用一个基类对象生成一个句柄类对象
C h2(h1); //用h1来初始化h2,它们对象指针指向同一个对象 a,计数指针指向同一个值。
B b;
C h3(b); //派生类对象生成一个句柄类对象
multiset<C> mc;
mc.insert(h1);
mc.insert(h2);
mc.insert(h3); //所有对象都能被完整保存
//注意:插入关联容器需要对象有比较函数
二、泛型句柄类
由于(一)中句柄类包含指向继承层次中某类型对象指针和计数式的复制控制,因此可以定义一个句柄类模版,管理指针和进行使用计数。
template <class T> class Handle {
public:// 默认构造函数Handle( T *p = 0 ): ptr(p), use( new int(1) ) { }// 复制构造函数Handle( const Handle& h ): ptr(h.ptr), use(h.use){ ++*use; }//重载操作符 * 和 -> ,const 和 非const版本T& operator*();T* operator->();const T& operator*() const;const T* operator->() const;// 重载操作符 =Handle& operator=( const Handle& );~Handle() { rem_ref(); }
private:T* ptr; // 对象指针int *use; // 引用计数void rem_ref(){if (--*use == 0) { delete ptr; delete use; } }
};
基类A、派生类B和模版类中的其它函数的定义与(一)中,不再重复。
泛型句柄类使用
class C{
public://默认构造函数C() : h() {}// 复制构造函数C( const A &a ) : h(a.clone()) {}//重载操作符 * 和 ->const A &operator*() const { return *h; }const A *operator->() const { return h.operator->(); }
private:Handle<A> h; // 使用句柄类
};
由于这个版本的类C没有指针成员,所以不需要复制控制成员,管理使用计数和相关对象的工作在 Handle 内部完成。
可以将使用模版句柄类定义的类C与原来的类C进行对比:两个类接口没有改变,因此类C的使用与上面相同。
C++句柄类(智能指针)小结相关推荐
- 【c++手记】句柄类智能指针
很多同学学习c++都会看的一本经典教材<Primer> 而在面向对象里面提及到一种概念-智能指针,而往往同学会出现以下的问题 [问题] 智能指针是不是一种指针? stl里面的智能指针是什么 ...
- 指针嵌套指针 拷贝_C++智能指针小结
C++中的智能指针包括auto_ptr, unique_ptr, shared_ptr, weak_ptr. 其中 auto_ptr已被弃用. unique_ptr unique_ptr是大部分情况下 ...
- android wp指针使用方法,Android智能指针RefBase、sp、wp解析
[TOC] 在Android系统中,Native层的代码基本都是C++写的,C++跟Java不一样,C++没有垃圾回收机制,C++代码中难于管理new出来对象的释放,稍有不慎就造成内存泄漏.针对此问题 ...
- android 绘指针,Android智能指针
"Yeah It's on. " 前言 在Android系统中,Native层的代码基本都是C++写的,C++跟Java不一样,C++没有垃圾回收机制,C++代码中难于管理new出 ...
- 虚幻C++入门个人笔记(3)——接口、智能指针、动画蓝图、行为树、EQS系统
接口 接口的词义广泛,用来陈述功能.选项,与其他程序结构进行沟通的方式.接口抽象出了交互结构,提供了两个未知逻辑交互的便捷性.对于编程中,如何更好地设计低耦合程序起到了至关重要的作用.设计者可以在互不 ...
- C++语法——详解智能指针的概念、实现原理、缺陷
目录 一.智能指针的概念 (一).智能指针的历史 (二).智能指针的使用 插曲.auto_ptr ①unique_ptr ②shared_ptr ③weak_ptr 二.智能指针的实现 三.智能指针的 ...
- C++智能指针shared_ptr、unique_ptr以及weak_ptr
目录 shared_ptr类 shared_ptr和unique_ptr都支持的操作 shared_ptr独有的操作 make_shared函数 shared_ptr自动销毁所管理的对象 由普通指针管 ...
- UE进阶实例40(STL与Unreal的智能指针)
STL智能指针 智能指针是C++11新引入的模板内存工具类,在std的命名空间下,早年有接触过cococs2d-x的开发者可能知道类似 于智能指针的功能原理,在有引用的时候,将引用计数器自增,丢失引用 ...
- C++智能指针:更简单、更高效的内存管理方法
C++智能指针:从新手到高手的心理密码C++ Smart Pointers: Psychological Passcodes from Beginner to Expert 智能指针简介 (Intro ...
- C++代理类,句柄(智能指针)_C++沉思录笔记
代理类 首先定义三个类: class Animal{ public:virtual void getName()=0;virtual void clone()=0; };class Cat:publi ...
最新文章
- 为什么“15。。。”会导致微信ANR?
- 测试晶面间距软件_【干货】高分辨TEM晶面间距的测量与标定丨DM软件
- android studio 模拟器中文乱码
- Eclipse相关问题总结
- python的类和实例化对象
- Java jdt 编辑_JDT入门
- 哪个内存更快?Heap或ByteBuffer或Direct?
- 负载均衡 > 用户指南 > 证书管理 > 证书要求
- Retrofit请求数据对错误以及网络异常的处理
- IDC商人应不应该给客户提供服务器测试?```
- adaptec SCSI卡管理和配置选项
- Android SD卡操作
- Matlab数字孪生
- 快手批量下载-支持作者所有视频无水印带标题
- xt5 连接android auto,2021年凯迪拉克XT6将添加无线Apple CarPlay和Android Auto
- maven 打包命令
- Gym包的安装与使用(新旧版本问题,Atari游戏支持问题)
- 携程网创始人季琦:互联网已不再有机会(转)
- python把两个图片合成一张图
- 全国各地dns服务器列表