在栈/堆上生成对象
Posted vector6_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在栈/堆上生成对象相关的知识,希望对你有一定的参考价值。
在栈/堆上生成对象
c++中,有时我们希望某种类型的对象有“自我析构”的能力,即能够"delete this",这样就要求该类型的对象被分配于堆中。另外还可能在某些场景下必须保证某一类型绝不会发生内存泄漏,即需要没有任何一个该类型的对象从堆中分配出来。
在堆中生成对象
我们知道非堆对象会在其定义点自动构造,并在其寿命结束时自动析构,所以要保证对象在堆中生成,只要让那些被隐式调用的构造函数和析构函数不合法就可以了。
更具体来说,最直接的方法是将构造函数和析构函数都声明为private,但由于一个类可能有许多个构造函数,其中包括copy constructor,以及default constructor,类的作者必须记住将他们都每一个都声明为private,这样比较麻烦。更简单的方法是使析构函数为private,而构造函数仍为public。例如,heap-based 类:
class HeapBased
public:
HeapBased()m_value = 0;
HeapBased(int value);
HeapBased(const HeapBased& rhs);
void destroy()const
delete this;
private:
~HeapBased(); //将dtor声明为private
private:
int m_value;
;
生成对象的操作:
HeapBased implicitObj; //隐式调用ctor,在对象的dtor稍后被隐式调用后会出错
HeapBased* pHeadBased = new HeapBased(); //succ
...
delete pHeadBased; //error! 试图调用private dtor,
pHeadBased->destroy(); //succ
但是还有一点需要考虑的,就是在存在继承和包含关系时,private dtor 会导致派生类出错。那么我们就需要在存在继承关系时,令析构函数为protected,而在存在包含关系时,将内含HeapBased对象变为包含一个指向HeapBased对象的指针。
class HeapBased
public:
HeapBased()m_value = 0;
HeapBased(int value);
HeapBased(const HeapBased& rhs);
void destroy()const
delete this;
protected:
~HeapBased(); //将dtor声明为private
private:
int m_value;
;
class DerivedHeapBased : public HeapBased //可以正常取用protected members
...
;
class ContainHeadpBased
...
private:
HeapBased* m_heapBased;
;
禁止对象生成于heap内
想要阻止将对象在堆内生成的操作,由于这些对象总是以new产生出来,我们可以让调用new的操作不合法。虽然我们不能够影响new operator 的能力(由语言内建),但是我们可以利用 new operator 总是调用 operator new 的原则,而operator new 是我们可以自行声明的。即我们可以将其声明为private。
例如,对不不希望将对象生成于heap 内的场景:
class NoneHeap
private:
static void* operator new(size_t size);
static void operator delete(void *ptr);
;
使用该类时:
NoneHeap pNoneHeap; //succ
static NoneHeap pNoneHeap2; //succ
NoneHeap* pNoneHeap3 = new NoneHeap();//error! 企图调用private operator new
除此之外,如果也需要禁止 由NoneHeap对象所组成的数组在堆内生成,可以将 operator new[] 和 operator delete[]也声明为 private。
而对于存在继承和包含关系的场景,由于 operator new 和 operator delete 都会被继承,所有派生类如果另外没有声明这些函数为public,那么便会继承这两个函数的private版本,即与父类的表现一致。
以上是关于在栈/堆上生成对象的主要内容,如果未能解决你的问题,请参考以下文章