企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持知识库和私有化部署方案 广告
[TOC] # 简介 当我们创建数组的时候,总是需要提前预定数组的长度,然后编译器分配预定长度的数组空间,在使用数组的时,会有这样的问题,数组也许空间太大了,浪费空间,也许空间不足,所以对于数组来讲,如果能根据需要来分配空间大小再好不过。 所以动态的意思意味着不确定性。 为了解决这个普遍的编程问题,在运行中可以创建和销毁对象是最基本的要求。当然c早就提供了动态内存分配(dynamic memory allocation),函数malloc和free可以在运行时从堆中分配存储单元。 然而这些函数在c++中不能很好的运行,因为它不能帮我们完成对象的初始化工作。 # new C++中解决动态内存分配的方案是把创建一个对象所需要的操作都结合在一个称为new的运算符里。当用new创建一个对象时,它就在堆里为对象分配内存并调用构造函数完成初始化。 ~~~ Person* person = new Person; 相当于: Person* person = (Person*)malloc(sizeof(Person)); if(person == NULL){ return 0; } person->Init(); ~~~ New操作符能确定在调用构造函数初始化之前内存分配是成功的,所有不用显式确定调用是否成功。 现在我们发现在堆里创建对象的过程变得简单了,只需要一个简单的表达式,它带有内置的长度计算、类型转换和安全检查。这样在堆创建一个对象和在栈里创建对象一样简单。 # delete new表达式的反面是delete表达式。**delete表达式先调用析构函数,然后释放内存**。正如new表达式返回一个指向对象的指针一样,**delete需要一个对象的地址**。 **delete只适用于由new创建的对象** 如果使用一个由malloc或者calloc或者realloc创建的对象使用delete,这个行为是未定义的。因为大多数new和delete的实现机制都使用了malloc和free,所以很可能没有调用析构函数就释放了内存。 如果正在删除的对象的指针是NULL,将不发生任何事,因此建议在删除指针后,立即把指针赋值为NULL,以免对它删除两次,对一些对象删除两次可能会产生某些问题。 ~~~ Person* person1 = new Person; Person* person2 = new Person("John",33); delete person1; delete person2; ~~~ # 用于数组的new和delete ~~~ 使用new和delete在堆上创建数组非常容易。 //创建字符数组 char* pStr = new char[100]; //创建整型数组 int* pArr1 = new int[100]; //创建整型数组并初始化 int* pArr2 = new int[10]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; //释放数组内存 delete[] pStr; delete[] pArr1; delete[] pArr2; ~~~ 当创建一个对象数组的时候,必须对数组中的每一个对象调用构造函数,除了在栈上可以聚合初始化,必须提供一个默认的构造函数 # `delete void*`可能会出错 如果对一个void*指针执行delete操作,这将可能成为一个程序错误,除非指针指向的内容是非常简单的,因为它将不执行析构函数.以下代码未调用析构函数,导致可用内存减少。 ~~~ class Person{ public: Person(char* name, int age){ pName = (char*)malloc(sizeof(name)); strcpy(pName,name); mAge = age; } ~Person(){ if (pName != NULL){ delete pName; } } public: char* pName; int mAge; }; void test(){ void* person = new Person("john",20); delete person; } ~~~