学完C语言动态内存管理C++动态内存管理我们就应该深入的去对比和了解两个的特性。

一 、 malloc/free和new/delete异同点

共同点:都是从堆上开辟空间,最后都需要手动释放
不同点:

  1. malloc/delete是标准库函数,new/delete是操作符
  2. new创建对象时会调用构造函数+开空间 ;delete会调用析构函数,而malloc/free只会开空间,而不会调用构造函数和调用析构函数
  3. malloc/free需要手动计算类型大小且返回值是 void*,在使用时必须强转 ,而new/delete可以自动计算空间并且返回对应类型的指针。
  4. malloc申请空间失败时返回NULL,因此在申请完之后必须判空,new不需要,但是new有出错会有异常捕获
  5. malloc申请的空间一定在堆上,new不一定(也有可能会在栈上),因为operator new函数可以重新实现
  6. new/delete比malloc/free效率要低,因为new/delete底层封装的是malloc/free。

二 、设计一个类,该类只能在堆上创建对象

分析:我们在用在函数内部定义变量----是在栈上开辟空间,若在全局区创建变量------则在数据段开辟空间
我们唯一知道能在堆上创建变量只有malloc相关函数,但是,malloc不会调用构造函数,pass。
那么我们到底要怎么做呢?
1.将构造函数作为私有成员,拷贝构造申明为私有成员,防止其他人调用在栈上创建对象
2. 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建

class Test
{
public:
	static Test* CreatObj()
	{
		return new Test;
	}

private:
	//将构造函数申明为私有
	Test() {};

	//防拷贝,但是这样是存在一个缺陷的,如果类中有friend函数该做法就会失效
	//这里我们只声明,不实现。因为实现可能会很麻烦,而我们本身可能不需要
	Test(const Test&t);

	//C++11提供的完美解决办法----删除函数
	Test(const Test&t) = delete;
private:
	int _data;
};
int main()
{
	Test *pt = Test::CreatObj();
	/*Test obj;
	Test obj3(*pt);*/
	return 0;
}

三 请设计一个类,该类只能在栈上创建对象

这个就比较简单了,只能在栈上创建对象,即不能再对上创建对象,这样的话我们只需要将new的功能屏蔽掉即可,当然operator new 和 定位new表达式也会随之屏蔽。

class StackType
{
public:
	static StackType CreatStackObj()
	{
		StackType obj;
		return obj;
	}
	void Print()
	{
		cout << "StackType::Print()" << endl;
	}
private:
	StackType()
	{}
	//将operator new 和 定位new表达式 功能屏蔽
	void* operator new(size_t n) = delete;
	void operator delete(void* p) = delete;
};
int main()
{
	StackType::CreatStackObj().Print();  // 相当于一个类
	StackType obj = StackType::CreatStackObj();
	obj.Print();
	return 0;
}