#include <iostream>
#include <string.h>
using namespace std;
class Students08{
public:
Students08(){
cout << "students08的默认构造函数"<< endl;
}
Students08(int a){
cout << "students08的有参构造函数"<< endl;
}
~Students08(){
cout << "students08析构函数" << endl;
}
};
int main()
{
// malloc和new区别
// 1.malloc和free属于库函数 new 和 delete属于运算符
// 2.malloc 不会调用构造函数 new会调用构造函数
// 3.malloc返回void* 在c++ 需要写强转。 new 返回创建的对象的指针
// Students08* p = new Students08;
// delete p; // 运行delete就会执行析构函数
// 注意1:不要使用void*去接收new出来的对象,后续delete的时候,就无法找到析构函数
// void* p = new Students08;
// delete p; // 无法调用析构函数
// 注意2:利用new 开辟数组
// int* p_i = new int[10];
// double* p_d = new double[10];
// 堆空间开辟数组,会调用默认构造函数,至少要保证有默认构造函数的存在才不会报错
Students08* p = new Students08[10];
// delete p; // 会报错 只删除第一个,剩余九个没有删除
delete [] p; // 删除堆空间的时候,需要在delete后加 []
// 栈上开辟数组,可以没有默认构造函数
Students08 arr[5] = {Students08(1), Students08(2),Students08(3),Students08(4),Students08(5)};
return 0;
}
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,以免对它删除两次,对一些对象删除两次可能会产生某些问题。
class Person{
public:
Person(){
cout << "无参构造函数!" << endl;
pName = (char*)malloc(strlen("undefined") + 1);
strcpy(pName, "undefined");
mAge = 0;
}
Person(char* name, int age){
cout << "有参构造函数!" << endl;
pName = (char*)malloc(strlen(name) + 1);
strcpy(pName, name);
mAge = age;
}
void ShowPerson(){
cout << "Name:" << pName << " Age:" << mAge << endl;
}
~Person(){
cout << "析构函数!" << endl;
if (pName != NULL){
delete pName;
pName = NULL;
}
}
public:
char* pName;
int mAge;
};
void test(){
Person* person1 = new Person;
Person* person2 = new Person("John",33);
person1->ShowPerson();
person2->ShowPerson();
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;
当创建一个对象数组的时候,必须对数组中的每一个对象调用构造函数,除了在栈上可以聚合初始化,必须提供一个默认的构造函数。
如果在new表达式中使用[],必须在相应的delete表达式中也使用[].如果在new表达式中不使用[], 一定不要在相应的delete表达式中使用[]. |