在栈/堆上生成对象

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版本,即与父类的表现一致。

以上是关于在栈/堆上生成对象的主要内容,如果未能解决你的问题,请参考以下文章

20165239其米仁增3

C++ 特殊类设计

C++如何只在堆上或者栈上生成对象

特殊类设计

如何判断一个对象是创建在栈中还是堆中

对象的私有成员是在堆上还是在栈上?