当我们创建数组的时候,总是需要提前预定数组的长度,然后编译器分配预定长度的数组空间,在使用数组的时候,可能数组的空间不太大,浪费空间,也许空间太大了,浪费空间,也许空间不足,所以对于数组来说,如果能够根据需要分配空间大小再好不过。
C语言中很好的提供了动态分配内存,malloc和free可以在运行时从堆中分配存储单元
对于最后一点,案例如下:
#include
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
class Maker {
public:
// explicit 关键字只能放在构造函数前面 构造函数只有一个参数或者其他参数有默认值时
// 防止编译器优化 Maker m = 10; 这种格式
Maker()
{
cout << "调用构造函数" << endl;
}
~Maker()
{
cout << "调用法国析构函数" << endl;
}
private:
int id;
};
void test01()
{
// 使用C语言方式申请堆区空间 不会调用构造函数 对象释放也不会调用析构函数
Maker* m = (Maker*)malloc(sizeof(Maker));
free(m);
}
int main()
{
//Maker m = 1;//err
return EXIT_SUCCESS;
}
C++解决动态内存分配的方案是把创建一个对象所需要的操作都结合在一个new的运算符中,当使用New创建一个对象时,它就在堆中为对象分配内存并且调用构造函数完成初始化
Person* person = new Person;
相当于:
Person* person = (Person*)malloc(sizeof(Person));
if(person == NULL)
{
return 0;
}
person->init();
案例代码:创建一个无参构造对象
#include
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
class Maker {
public:
// explicit 关键字只能放在构造函数前面 构造函数只有一个参数或者其他参数有默认值时
// 防止编译器优化 Maker m = 10; 这种格式
Maker()
{
cout << "调用构造函数" << endl;
}
~Maker()
{
cout << "调用析构函数" << endl;
}
private:
int id;
};
void test02()
{
// 用New方式申请堆区空间 会调用类的构造函数
Maker* m = new Maker;// 这种方式调用的是无参构造函数
delete m;
m = NULL;
}
void test01()
{
// 使用C语言方式申请堆区空间 不会调用构造函数 对象释放也不会调用析构函数
Maker* m = (Maker*)malloc(sizeof(Maker));
free(m);
}
int main()
{
//Maker m = 1;//err
test02();
return EXIT_SUCCESS;
}
案例代码:创建一个有参数构造对象
#include
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
class Maker {
public:
// explicit 关键字只能放在构造函数前面 构造函数只有一个参数或者其他参数有默认值时
// 防止编译器优化 Maker m = 10; 这种格式
Maker(int a)
{
cout << "调用构造函数" << endl;
id = a;
}
~Maker()
{
cout << "调用析构函数" << endl;
}
private:
int id;
};
void test02()
{
// 用New方式申请堆区空间 会调用类的构造函数
Maker* m = new Maker(1);
delete m;
}
void test01()
{
// 使用C语言方式申请堆区空间 不会调用构造函数 对象释放也不会调用析构函数
Maker* m = (Maker*)malloc(sizeof(Maker));
free(m);
}
int main()
{
//Maker m = 1;//err
test02();
return EXIT_SUCCESS;
}
总结:
#include
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
// new 创建基础类型的数组
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; 这样写也可以
*(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()
{
//Maker m = 1;//err
test01();
return EXIT_SUCCESS;
}
#include
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()
{
//Maker m = 1;//err
test02();
return EXIT_SUCCESS;
}
#include
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;
}
// delete void* 可能会出错 不会调用对象的析构函数
void test03()
{
void* m = new Maker;// 无参构造申请一个对象
// 如果使用void * 来接new的对象 那么delte时不会调用析构函数
delete m;
}
int main()
{
//Maker m = 1;//err
test03();
return EXIT_SUCCESS;
}
#include
using namespace std;
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
class Maker {
public:
Maker()
{
cout << "构造函数" << endl;
}
~Maker()
{
cout << "析构函数" << endl;
}
};
// delete void* 可能会出错 不会调用对象的析构函数
void test03()
{
void* m = new Maker;// 无参构造申请一个对象
// 如果使用void * 来接new的对象 那么delte时不会调用析构函数
// 在编译阶段 那么编译器就确定好了函数的调用地址
// C++编译器不认识void* 不知道void* 指向哪一个函数 所以会调用析构函数
// 这种编译方式叫做静态联编
delete m;
}
int main()
{
//Maker m = 1;//err
test03();
return EXIT_SUCCESS;
}
错误写法:
void test04()
{
Maker *m = new Maker;//c++
free(m);//c
}
c++和C的共同和区别之处:
共同:都是申请堆区空间和释放堆区空间
区别:C++会调用构造和析构函数