C++学习笔记(五)——使用new/delete创建栈/堆对象

C++学习笔记(五)——使用new/delete创建栈/堆对象

创建栈对象,类中必须要由构造函数与析构函数(系统默认给的也可以),创建堆对象,除了类中必须要由构造函数与析构函数(系统默认给的也可以)外,还有一个条件就是new/delete可用。不论是只能创建栈对象还是只能创建堆对象,都必须要理解new/delete的工作机理才可以。

new/delete的工作机理

使用new表达式时发生的三个步骤:

  • 调用名为operator new的标准库函数,分配足够大的原始的未类型化的内存,以保存指定类型的一个对象;
  • 运行该类型的一个构造函数去初始化对象
  • 返回指向新分配并构造的构造函数对象的指针
    使用delete表达式时,发生的步骤:
  • 调用对象的析构函数
  • 调用名为operator delete的标准库函数释放该对象所用的内存
    切记:在类外使用new/delete时,new/delete调用构造/析构函数的方式是类外调用,即private内的构造/析构函数new/delete无法调用;在类内使用new/delete时,new/delete调用构造/析构函数的方式是类内调用,即private内的构造/析构函数new/delete可以调用。

只能创建栈对象,不能创建堆对象

依据上面的介绍,要实现这个功能就必须:== 使类外不得调用new/delete==。只有这样才不会产生堆对象。实现代码如下(代码5-1)

 ///
 /// @file    Student.cc
 /// @date    2019-02-09 21:38:35
 ///
 
#include <string.h>
#include <stdlib.h>
#include <iostream>
using std::cout;
using std::endl;

//要求:只能生成栈对象
class Student
{
	public:
		Student(int id,  const char * name)
			:_id(id)
			 ,_name(new char[strlen(name)+1])
	{
		strcpy(_name, name);
		cout << "Student " << endl;
	}

		void print() const
		{
			cout << "id: " << _id << endl;
			cout << "name : " << _name << endl;
		}

		~Student()
		{
			cout << "~Student()" << endl;
		}
	private:

		void * operator new(size_t size);
//将new/delete放在private区重载,就不会创建堆对象了,但是还可以
//在类内用new/delete使用堆空间。
		void operator delete(void * ret);
		int _id;
		char * _name;
};

int main()
{
//	Student * ps1 = new Student(100,"Mike");
	Student ps2(110,"Lili");
//	ps1->print();
//	delete ps1;  //ps1是堆对象不会自动调用析构函数,必须手动删除
	ps2.print();
	return 0;
}

只能创建堆对象,不能创建栈对象

创建栈对象只需要构造/析构函数;创建堆对象时,需要调用new/delete,然后new/delete又会调用构造/析构函数。所以实现这个功能有两种方法:

  1. 将构造函数放入private,然后重载new函数:这个的实现目前存在难点即:当调用new时,先要执行operator new然后返回一个指针,之后再以类外调用的形式来调用构造函数。当构造函数是private时,new就没有办法调用构造函数了。就算类内设计了一个调用构造函数的函数,也没有办法调用该函数,因为对象都还没有创建出来,怎么来调用来对象内的函数呢?!,所以该方法目前没有办法实现。
  2. 将析构函数放入private,然后重载delete函数;

将析构函数放入private,然后重载delete函数

 ///
 /// @file    heapStudent.cc
 /// @date    2019-02-09 21:38:35
 ///
 
#include <string.h>
#include <stdlib.h>
#include <iostream>
using std::cout;
using std::endl;

//栈对象的建立依赖于构造和析构函数的存在
//堆对象的建立依赖于new/delete的存在
//new/delete的实现以来与构造与析构函数的存在
class Student
{
	public:
		Student(int id, const char * name)
			:_id(id)
			 ,_name(new char[strlen(name) + 1]())
	{
		strcpy(_name, name);
		cout << "Student " << endl;
	}

		void print() const
		{
			cout << "id: " << _id << endl;
			cout << "name : " << _name << endl;
		}

		void destroy()
		{
			delete this;
		}

		void * operator new(size_t size)
		{
			cout << "new " << endl;
			void * ret = malloc(size);
			return ret;
		}

		void operator delete(void * ret)
		{
			cout << "delete " << endl;
			free(ret);
		}
	private:
		~Student()
		{
			delete( _name);
			cout << "~Student()" << endl;
			//delete this;//这样写会造成死循环:delete this->~Student -> delete this
		}
		int _id;
		char * _name;
};

int main()
{
//	Student ps(99,"Jack");    //创建失败
	Student * ps1 = new Student(100,"Mike");
	ps1->print();
	ps1->destroy();//在destroy内调用delete这是就可以访问private区内的析构函数了
//	delete ps1;  //ps1是堆对象不会自动调用析构函数,必须手动删除
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值