1. C语言和C++中动态内存分配的区别
区别 | C语言 | C++ |
---|---|---|
申请内存 | malloc | new 和new[] |
释放空间 | free | delete 和delete[] |
作用域 | 内置类型 | 所有类型 |
new / delete 是两个操作符,malloc / free是两个系统函数
2. new / delete 是如何实现操作的?
new 两步操作 | delete 两步操作 |
---|---|
1).调用 :: operator new( )分配内存 | 1).调用该类的析构函数释放所占资源 |
2).调用该类的构造函数进行初始化 | 2).调用 :: operotor delete( )释放内存 |
3. operator new / operator delete
先来看看两个函数的调用方式:
void* operator new (size_t)
//用new 申请一块size_t大小的内存,需要该空间的返回值,来判断内存是否申请成功
void operator delete(void*)
//用delete 释放一块空间,不需要返回值,但需要参数指明释放那一块空间,得保证你释放的空间存在
- operator new 更具体的形式,有如下三种:(稍作了解)
//异常抛出形式:
void* operator new(std::size_t size) throw(std::bad_alloc);
//不抛出异常形式:
void* operator new(std::size_t size,const std::nothrow_t& nothrow_value) throw();
//placement形式:
void* operator new(std::size_t size,void*ptr)throw();
使用new / delete 函数时,编译器会默认调用 operator new ( ) 和 operator delete( ),但既然是函数,就可以实现重载
代码验证:
#include<iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A constructor" << endl;
}
void* operator new(size_t size)
{
cout << "this is new A" << endl;
return ::operator new(size);
}
void operator delete(void* ptr)
{
cout << "this is delete A" << endl;
return ::operator delete(ptr);
}
~A()
{
cout << "A destructor" << endl;
}
};
int main()
{
A *a = new A;
delete a;
system("pause");
return 0;
}
打印结果:
operator new 申请一个内存失败时,它会进行如下操作:
1)如果存在客户规定的处理函数,则调用处理函数(new_handler),如果不存在,抛出异常。
——new_handler 的模型为:void(*new_hanlder)( )2)继续申请内存
3)判断是否申请成功,如果成功——返回内存指针,如果失败——转向步骤1)- operator的注意事项:
1)重载时,-必须带void* 类型的返回值
2)重载时,-必须带有你申请内存 size_t 大小的参数
3)重载时,可以调用除 sizez-t 以外的其他参数
5. new[ ] / delete[ ]
- new[]如何分配空间的?
会额外多分配四个字节存储数组元素个数,分配完成后指针会向后偏移4个字节。
- delete[]如何释放正确的空间大小?
将指针向前偏移4个字节,获取元素个数,再挨个释放。
6. delete / delete[ ] 的区别
区别 | delete | delete[ ] |
---|---|---|
释放对象 | new分配的单个对象的指针指向的空间 | new分配的数组的指针指向的空间 |
操作步骤 | 调用这个对象的析构函数释放所占资源,再释放这段内存空间 | 调用数组中每一个元素的析构函数释放资源,再释放这段内存空间 |
单个类对象 | 可以使用 | 可以使用(有一个就调一次析构函数) |
数组对象 | 不可使用(此时只调用下标为0 的那个元素的析构函数) | 可以使用 |
代码分析:
(1)
//实例一:
int*p=new int;(内置类型不需要调析构函数和构造函数)
delete p;//可以,p指向了一个int的内置类型大小的空间,delete直接释放了它。
delete []p;//可以
(2)
//实例二:
int*p=new int[10]();可以
delete p;内置类型不需要调析构函数
delete []p;可以,效果同上
delete p;
delete [ ]p;
(3)
//实例三:
A*p=new A();
delete p;//可以
delete []p;//可以
delete p;
delete [ ]p;
(4)
//实例四:
A*p=new A[2]();
delete p;//不行,只会调用p[0]的析构函数
delete[] p;可以,会调每个数组元素的析构函数
delete p;
delete [ ]p;