C++程序通常要为一整组对象分配内存,随后将其同时释放
- 定义一个包含一整组对象的集合的类
让一个集合包含不相关的类的对象的一个好方法:多重继承
问题:交互式或长时间运行的程序中常有一堆各式各样的C++对象需要一块释放
设计方案
- 使用类来表示概念:需要一个类表示“一些要一起释放的对象”
|
|
Cluster类的对象c必须明显包含将在某个适当的时候被释放的其他对象
必须有一种方法分配一个对象到某个特定的Cluster里
T* tp = new(c) T;
类型T必须有一个成员
void* T::operator new(size_t, Cluster&);
- 对类型T的调整限制了Cluster的用途
要能将任何自定义类的对象放入簇中
- 避免修改已经存在了的T的定义
使用继承和一个间接层(indirection)
- 使用多重继承:由基类ClusterItem派生出的类的对象可以分配在簇中
|
|
- 有些C++实现限定只要有
operator new
成员函数就必须保证有一个只有一个参数的类型的operator new
- 保证该类的对象可以用普通的new表达式分配
- 如果不希望这样做:将普通的
operator new
私有化
- 如果不希望这样做:将普通的
|
|
- 缺省构造函数
- 虚析构函数
- ClusterItem对象的销毁仅伴随Cluster对象的销毁
- 不公有化ClusterItem的析构函数
- Cluster作为一个友元
|
|
- Cluster类需要构造函数、析构函数
- 将ClusterItem作为友元
- 限定Cluster对象的复制操作:不考虑该操作的含义
|
|
实现
- 写一个容器
- Cluster中保存一个ClusterItem的链表
- 会按与创建是相反的顺序删除ClusterItem:局部变量分配的镜像(回收策略)
|
|
类ClusterItem中的虚析构函数可以删除用户任何从ClusterItem派生出来的类的对象
使用
new(c) T;
分配某个继承自类ClusterItem的类T的对象时,会把适当的Cluster作为成员ClusterItem::operator new
的参数- 唯一判断Cluster是否有效的时机
operator new
的任务是分配裸内存(raw memory)而不是处理已经构造好的对象- 将ClusterItem链接到Cluster链中的工作应该由ClusterItem的构造函数完成
operator new
要在构造函数能看到的地方保存Cluster- (源文件范围内可见的)静态变量
static Cluster* cp;
- (源文件范围内可见的)静态变量
- 只在成员函数定义的文件中有效,不必担心名字问题
|
|
- 定义声明了的缺省的
operator new
,即使不使用(一些C++实现的要求)
|
|
加入继承
- 使用这些类的方法是从ClusterItem派生新类
|
|
- 两个问题
- 对某些未定义的类进行簇式分配
- ClusterItem的析构函数私有,不能声明任何ClusterItem派生类局部变量
|
|
- new表达式分配一个类型为MyClusteredClass的对象
- 将该对象的地址转换成类型
MyClass*
的
- 将该对象的地址转换成类型
- 只要不试图删除这个指针,可像任何其他MyClass指针一样使用
MyClusteredClass需再定义缺省构造函数等
Summary
问题解决的关键在于实现之前正确阐明问题
《C++沉思录(Cplusplus Thinking)》笔记