面试题4:堆栈内存分配

题目:

编写C++中的两个类,一个只能在栈中分配空间,一个只能在堆中分配空间。

解答:

要写出这两个类,首先要了解堆栈分配内存情况,一个经过编译的C/C++占用的内存分为以下几个部分:

1.栈区:由编译器自动分配和释放,存放函数的参数值、局部变量的值等,甚至函数的调用过程都是用栈来完成的。其操作方式类似于数据结构中的栈。

2.堆区:一般由程序员手动申请及释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式类似于链表。

3.全局区(静态区):全局变量和静态变量存储是放在一起的,初始化的全局变量和静态变量在未初始化的全局变量和未初始化的静态变量相邻的另一块区域。程序结束后由系统释放空间。

4.文字常量区:常量字符串就放在这里,程序结束后由系统释放空间。

5.程序代码区:存放函数体的二进制代码。

#include<iostream>  
using namespace std;
//只能在堆上分配内存  
class HeapOnly
{
public:HeapOnly(){cout << "Construct." << endl;}void destory(){delete this;}private:~HeapOnly(){}
};//只能在栈上分配空间  
class StackOnly
{
public:StackOnly(){}~StackOnly(){}private:void* operator new(size_t size)   //将new操作符私有化,在外面无法调用  {}
};int main()
{HeapOnly *hO = new HeapOnly();hO->destory();//HeapOnly he; //编译错误:HeapOnly::~HeapOnly”: 无法访问 private 成员(在“HeapOnly”类中声明),所以不能通过栈来分配这个对象的空间  //delete *hO;    //编译错误:'delete' : cannot convert from 'HeapOnly' to 'void*'StackOnly so;//StackOnly *st=new StackOnly();  //StackOnly::operator new”: 无法访问 private 成员(在“StackOnly”类中声明)  
}

注意:析构函数定义为私有的,就阻止了用户在类域外对析构函数的使用。这表现在如下两个方面:

1.禁止用户对此类型的变量进行定义,即禁止在栈内存空间内创建此类型的对象。要创建对象,只能用new在堆上进行。

2.禁止用户在程序中使用delete删除此类对象。对象的删除只能在类内实现,也就是说只有类的实现者才有可能实现对对象的delete,用户不能随便删除对象。如果用户想删除对象,只能按照类的实现者提供的方法进行。

将析构函数设为private,除了限制栈对象生成,还限制了继承。如果只限制栈对象,不限制继承,可以将析构函数声明为protected。