目录
五、【new】和【delete】对于自定义类型会调用构造函数和析构函数
C
一、C语言和C++内存管理方式
C语言内存管理方式:
在C语言中使用库函数【malloc】、【calloc】、【realloc】、【free】来实现动态内存管理
具体可以看一下此篇文章:C语言——动态内存分配_c语言 重新动态分配内存-CSDN博客
C++内存管理方式:
在C++中我们依然可以使用C语言中的库函数【malloc】、【calloc】、【realloc】、【free】来实现动态内存管理
但是C++中提出了自己的内存管理方式:通过【new】和【delete】操作符进行动态内存管理
1、C语言和C++内存管理方式区别
相同点:
- 都是从堆上申请空间,并且需要用户手动释放
不同点:
- malloc和free是函数,new和delete是操作符
- malloc申请的空间不会初始化,new可以初始化
- malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可,如果是多个对象,[]中指定对象个数即可
- malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
- malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
- 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理释放
2、【new】和【delete】的好处
【new】/【delete】 相较于 【malloc】/【free】使用更加简单
【new】/【delete】的功能更加强大【new】/【delete】
二、使用【new】来分配内存
我们要告诉【new】,需要为那种数据类型分配内存。【new】将找到一个长度合适的内存卡,并返回该内存块的地址。我们的责任就是将该地址赋予给一个指针
格式:
TypeName * Name = new TypeName
动态申请一个类型空间:
int main()
{
// 动态申请一个类型的空间
int* ptr1 = new int;
double* ptr2 = new double;
long long* ptr3 = new long long;
Test* ptr4 = new Test;
return 0;
}
class Test
{
public:
Test(int n = 1)
:num(n)
{}
int num;
};
动态申请一个类型空间并初始化:
int main()
{
// 动态申请一个类型的空间并初始化
int* ptr1 = new int(1);
double* ptr2 = new double(1.0);
long long* ptr3 = new long long(1);
Test* ptr4 = new Test(1);
return 0;
}
class Test
{
public:
Test(int n = 1)
:num(n)
{}
int num;
};
三、使用【new】来创建动态数组
1、创建动态数组
在C++中,创建动态数组很容易。只要将数组的元素类型和元素个数告诉【new】就行。必须要在类型后面加上方括号,其中包含元素个数
格式:
TypeName* Name = new TypeName [ elements ]
使用【new】运算符可以确保内存块足以存储【elements】个类型的【TypeName】的元素,而【Name】指向了数组的第一个元素
动态申请一个数组:
int main()
{
// 动态申请一个数组
int* ptr1 = new int[10];
double* ptr2 = new double[10];
long long* ptr3 = new long long[10];
Test* ptr4 = new Test[10];
return 0;
}
class Test
{
public:
Test(int n = 1)
:num(n)
{}
int num;
};
动态申请一个数组并初始化:
int main()
{
// 动态申请一个数组并初始化
int* ptr1 = new int[10] {1, 2, 3};
double* ptr2 = new double[10] {1.0, 2.0, 3.0};
long long* ptr3 = new long long[10] {1, 2, 3};
Test* ptr4 = new Test[10]{ 1,2,3 };
return 0;
}
class Test
{
public:
Test(int n = 1)
:num(n)
{}
int num;
};
【注意】
- 动态申请一个数组并初始化,对于内置类型的不完全初始化编译器会自动补0
- 动态申请一个数组并初始化,对于自定义类型的不完全初始化编译器会自动的调用构造函数进行初始化,没有相应的构造函数就会报错
调试窗口:
2、使用动态数组
C和C++内部都是使用指针来处理数组,而数组和指针基本等价。因此对于如何使用【new】运算符开辟的数组:只要把指针当作数组名使用即可
就是说,对于第一个元素可以使用【Name [ 0 ]】,而不是【*Name】;对于第二个元素可以使用【Name [ 1 ]】,而不是【*( Name + 1 )】,以此类推
示例:
class Test
{
public:
Test(int n = 1)
:num(n)
{}
int num;
};
ostream& operator<<(ostream& out, const Test& t)
{
out << t.num;
return out;
}
int main()
{
// 动态申请一个数组并初始化
int* ptr1 = new int[10] {1, 2, 3};
double* ptr2 = new double[10] {1.0, 2.0, 3.0};
long long* ptr3 = new long long[10] {1, 2, 3};
Test* ptr4 = new Test[10]{ 1,2,3 };
//动态数组的访问
for (int i = 0; i < 10; i++)
{
cout << ptr1[i] << " ";
}
cout << endl;
//动态数组的访问
for (int i = 0; i < 10; i++)
{
cout << *(ptr2 + i) << " ";
}
cout << endl;
//动态数组的访问
for (int i = 0; i < 10; i++)
{
cout << ptr3[i] << " ";
}
cout << endl;
//动态数组的访问
for (int i = 0; i < 10; i++)
{
cout << *(ptr4 + i) << " ";
}
cout << endl;
return 0;
}
结果:
四、使用【delete】来释放内存
当需要内存时,可以使用【new】来申请空间,当不需要【new】申请的内存时,可以使用【delete】来释放空间。使用【delete】时,后面要加上指向内存块的指针
示例:
int main()
{
// 动态申请一个内存空间
int* ptr = new int;
//释放空间
delete ptr;
return 0;
}
【delete】将释放【ptr】指向的内存,但不会删除【ptr】指针本身,也就是说【delete】后的【ptr】为野指针。【prt】可以重新指向另一个动态开辟的内存
规则:
- 不要使用【delete】来释放不是【new】开辟的内存
- 不要使用【delete】释放同一个内存两次
- 如果使用【new [ ] 】为数组开辟内存,应该使用【delete [ ] 】来释放内存
- 如果使用【new】为一个数据开辟内存,应该使用【delete】来释放内存
- 对空指针的应用【delete】是安全的
1、不要使用【delete】释放同一个内存两次
int main()
{
//不要使用【delete】释放同一个内存两次
int* ptr = new int;
delete ptr; //ok
delete ptr; //erorr
return 0;
}
2、不要使用【delete】来释放不是【new】开辟的内存
int main()
{
//不要使用【delete】来释放不是【new】开辟的内存
int num = 10;
int* ptr = #
delete ptr; //erorr
return 0;
}
3、匹配使用【delete】释放空间
如果使用【new】时带方括号,则使用【delete】时也因该带方括号。如果使用【new】时不带方括号,则使用【delete】时也因该不带方括号。它们之间要匹配使用
【new】与【delete】的格式不匹配导致后果是不确定的,因此我们不能依赖于某种特定的行为
示例:
int main()
{
//【new】与【delete】要匹配使用
int* ptr1 = new int;
int* ptr2 = new int[10];
delete ptr2; //erorr
delete[] ptr1; //erorr
return 0;
}
五、【new】和【delete】对于自定义类型会调用构造函数和析构函数
【new】和【delete】对于内置类型相较于C语言只有用法上有区别,但是功能上区别不大
【new】和【delete】对于自定义类型相较于C语言就有本质上的区别了,【new】和【delete】对于自定义类型除了开空间还会调用构造函数和析构函数,而【malloc】和【free】只会开空间
示例:
class Test
{
public:
//构造函数
Test(int n = 1)
:num(n)
{
cout << "构造函数" << endl;
}
//析构函数
~Test()
{
cout << "析构函数" << endl;
}
int num;
};
int main()
{
//new对于【自定义类型】除了开空间还会调用构造函数
Test* ptr = new Test;
//delete对于【自定义类型】会调用析构函数
delete ptr;
return 0;
}
结果:
如果自定义类型没有默认构造函数,那么编译器就会报错
示例:
class Test
{
public:
//构造函数
Test(int n)
:num(n)
{
cout << "构造函数" << endl;
}
//析构函数
~Test()
{
cout << "析构函数" << endl;
}
int num;
};
int main()
{
//new对于【自定义类型】除了开空间还会调用构造函数
Test* ptr = new Test;
//delete对于【自定义类型】会调用析构函数
delete ptr;
return 0;
}
结果:编译报错
标签:long,浅谈,int,C++,内存,Test,new,delete From: https://blog.csdn.net/LVZHUO_2022/article/details/144170572