您的位置:首页 > 编程语言 > C语言/C++

more effective C++设计模式 要求(或禁止)对象产生于heap中

2017-09-18 14:35 471 查看
要求(或)禁止对象产生于heap中

有时候我们想让某种对象具有自杀的能力,所以我们必须要求对象存在堆中,以便我们调用delete this.有的时候堆空间非常宝贵,并且我们需要保证不发生内存泄露所以我们要对象全为栈对象,必须禁止对象产生于堆中。

要求对象产生于堆中

一种典型的手法是把析构函数声明为protected,然后给类一个伪构造函数destroy来调用delete this.下面我们来看例子:

class UPNumber
{
public:
UPNumber();
UPNumber(int initValue);
UPNumber(const UPNumber& rhs);
void destroy() { delete this; }
protected:
~UPNumber();
}这里注意我们析构函数声明为protected,以保证该类可以被继承(拥有private 构造函数以及析构函数的类 不能被继承),当我们以这种做法来实现的时候,其他的类如果想要该类作为其成员,只能存储器指针。
但是这里还是存在一些问题,如果我们有一个类继承了UPNumber,比如说是NonNegativeUPNumber 。然后我们定义了NonNegativeUPNumber n;此时派生类的基类部分是存在于栈之中的,所以我们严格要求对象产生于栈中不太合适。所以我们在返回去看我们之前提出的问题,我们想知道对象是否产生于堆中,或者我们想调用delete this.是时候重新重新审视我们的需求了。说到底我们可能的需求是判断一个指针的删除操作是否安全,并不是判断对象是否一定位于堆中。

位于堆中的对象不一定就能够被安全的删除,比如当作为一个类的成员变量的时候。

一个有效的办法就是继承一个class HeapTracked:

实现如下:

class HeapTracked
{
private:
typedef const void* RawAddress;
static list<RawAddress> address;//用于存储被operator new 分配的内存,需要我们注意的是,真的需要给这个类进行如此繁重的记录工作吗 慎重!
public:
class MissAddress{};//用于抛出异常
static void *operator new(size_t size);
static void*operator delete(size_t size);
virtual ~HeapTracked()=0;//为了调用dynamic_cast<const void*>
bool isHeaped() const;//调用dynamic_cats<void*>对this进行list查询
}

总结起来如果一个类不会被继承,那么让他只能产生于堆之中是非常好实现的(将析构函数声明为private),但是如果是可以被继承,并且严格要求被产生于堆之中,那么基本很难实现。那么要判断一个类的对象能不能被delete,一个好的实现就是让他继承HeapTracked,但是这也带来复杂的记录工作,需要慎
4000
重考虑是否需要这种实现。
禁止对象产生于heap之中

我们只需要在类中把声明private的void* operator new(size_t  size) 函数.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: