?当我们创建数组的时候,总是需要提前预定数组的长度,然后编译器分配预定长度的数组空间,在使用数组的时候,可能数组的空间不太大,浪费空间,也许空间太大了,浪费空间,也许空间不足,所以对于数组来说,如果能够根据需要分配空间大小再好不过。
?C语言中很好的提供了动态分配内存,malloc和free可以在运行时从堆中分配存储单元
一、C语言创建和销毁堆区空间出现的问题
- 程序员必须确定对象的长度
- malloc返回一个void* 指针,C++不允许将void*赋值给其他指针,必须进行强制转换
- malloc可能申请内存失败,所以必须判断返回值来确保内存分配成功
- 用户在使用对象之前必须记住对他初始化,构造函数不能显示调用初始化(构造函数都是由编译器进行调用的),用户有可能忘记调用初始化函数
对于最后一点,案例如下:
#include<iostream>
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
class Maker {
public:
Maker()
{
cout << "调用构造函数" << endl;
}
~Maker()
{
cout << "调用法国析构函数" << endl;
}
private:
int id;
};
void test01()
{
Maker* m = (Maker*)malloc(sizeof(Maker));
free(m);
}
int main()
{
return EXIT_SUCCESS;
}
二、C++创建和销毁堆区空间
C++解决动态内存分配的方案是把创建一个对象所需要的操作都结合在一个new的运算符中,当使用New创建一个对象时,它就在堆中为对象分配内存并且调用构造函数完成初始化
Person* person = new Person;
相当于:
Person* person = (Person*)malloc(sizeof(Person));
if(person == NULL)
{
return 0;
}
person->init();
案例代码:创建一个无参构造对象
#include<iostream>
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
class Maker {
public:
Maker()
{
cout << "调用构造函数" << endl;
}
~Maker()
{
cout << "调用析构函数" << endl;
}
private:
int id;
};
void test02()
{
Maker* m = new Maker;
delete m;
m = NULL;
}
void test01()
{
Maker* m = (Maker*)malloc(sizeof(Maker));
free(m);
}
int main()
{
test02();
return EXIT_SUCCESS;
}
案例代码:创建一个有参数构造对象
#include<iostream>
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
class Maker {
public:
Maker(int a)
{
cout << "调用构造函数" << endl;
id = a;
}
~Maker()
{
cout << "调用析构函数" << endl;
}
private:
int id;
};
void test02()
{
Maker* m = new Maker(1);
delete m;
}
void test01()
{
Maker* m = (Maker*)malloc(sizeof(Maker));
free(m);
}
int main()
{
test02();
return EXIT_SUCCESS;
}
总结:
- 为什么要有新的方法申请和释放堆区空间?
- C++中申请堆区空间和释放堆区空间用什么关键字
- 申请堆区空间使用new,释放堆区空间使用delete
三、new和delete用于申请基本类型的数组
#include<iostream>
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
void test01()
{
int* pInt = new int[10]{1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < 10; i++)
{
*(pInt + i) = i + 1;
}
for (int i = 0; i < 10; i++)
{
cout << pInt[i] << " ";
}
cout << endl;
char* pChar = new char[64];
memset(pChar,0,sizeof(char) * 64);
strcpy(pChar,"小花");
cout << pChar << endl;
delete[] pInt;
delete[] pChar;
}
int main()
{
test01();
return EXIT_SUCCESS;
}
四、new创建对象数组
#include<iostream>
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
class Maker {
public:
Maker()
{
cout << "构造函数" << endl;
}
~Maker()
{
cout << "析构函数" << endl;
}
};
void test02()
{
Maker* ms = new Maker[2];
delete[] ms;
}
int main()
{
test02();
return EXIT_SUCCESS;
}
五、delete void * 可能会出错,不会调用对象的析构函数
#include<iostream>
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
class Maker {
public:
Maker()
{
cout << "构造函数" << endl;
}
~Maker()
{
cout << "析构函数" << endl;
}
};
void test02()
{
Maker* ms = new Maker[2];
delete[] ms;
}
void test03()
{
void* m = new Maker;
delete m;
}
int main()
{
test03();
return EXIT_SUCCESS;
}
#include<iostream>
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
class Maker {
public:
Maker()
{
cout << "构造函数" << endl;
}
~Maker()
{
cout << "析构函数" << endl;
}
};
void test03()
{
void* m = new Maker;
delete m;
}
int main()
{
test03();
return EXIT_SUCCESS;
}
六、C和C++的申请和释放堆区空间不要混用
错误写法:
void test04()
{
Maker *m = new Maker;
free(m);
}
c++和C的共同和区别之处:
共同:都是申请堆区空间和释放堆区空间
区别:C++会调用构造和析构函数
|