new、malloc区别。free、delete区别
- malloc free 称为C的库函数
- new delete 称作运算符
1
2
3
4
5int *p = malloc();
free(p);
==================================
int *p = new int(...);
delete p;
malloc和new的区别?
new调用operator new,operator new调用malloc- malloc按字节开辟内存的;new开辟内存时需要指定类型 new int[10];所以malloc开辟内存返回的都是void*
- malloc只负责开辟空间,new不仅仅有malloc的功能,可以进行数据的初始化
new int(20); new int[20](); - malloc开辟内存失败返回nullptr指针;new抛出的是bad_alloc类型的异常
1
2
3
4
5
6
7
8
9
10
11
12
13int* p = (int*)malloc(sizeof(int));
if (p == nullptr) cout << "wrong" << endl;
try {
int* pp = new int(10);
}
catch (const bad_alloc& e) {
}
// int *pp = new int[20]; 在堆上开辟后不会初始化
int *pp = new int[20](); // 在堆上开辟后会初始化
delete []pp;
new
- 先分配
memory,再调用ctor(构造函数) Complex* pc = new Complex(1,2);- 编译器转化为
1
2
3
4Complex *pc;
void* mem = operator new(sizeof Complex); //分配内存 operator new 内部调用malloc(n)
pc = static_cast<Complex*>(mem); //强转
pc->Complex::Complex(1,2); //构造 Complex::(pc,1,2); pc即为thisoperator new
- operator new仅仅负责开辟内存,在内存上写什么、任何与对象内容有关系的事情都与operator new无关
1
2
3
4
5
6
7void *operator new(size_t size)
{
void *p = malloc(size); // 按Byte
if(p==nullptr)
throw bad_alloc();
return p;
}
有几种new
1 | int *p1 = new int(20); |
free和delete的区别?
- delete调用operator delete,operator delete 调用free
- delete (int*)p: 调用析构函数;再free(p)
new和delete能混用吗?C++为什么区分单个元素和数组的内存分配和释放呢?
new delete
new[] delete[]
对于普通的编译器内置类型 new/delete[] new[]/delete
自定义的类类型,有析构函数,为了调用正确的析构函数,那么开辟对象数组的时候,
会多开辟4个字节,记录对象的个数
delete
- 先调用
dtor,再释放内存memory Complex *pc = new Complex(1,2);delete pc- 编译器转化为
1
2
3Complex::~Complex(pc); //dtor 调用析构函数是为了释放(基类、派生类)成员指针管理的内存,而不会释放本对象本身占据的内存。
// 如果本对象是栈上的,那么离开作用域后会自动调用析构函数 ,然后释放内存(也就是说析构函数何释放本对象内存是两回事)。很可惜,new出来的对象在堆上,得手动调用operator delete释放。(所以要保证pc指向得位置是对的(虚基类里就不对))
operator delete(pc); //释放memory 内部调用 free(pc)
operator delete
- operator delete仅仅负责释放内存,在内存上析构什么对象、任何与对象内容有关系的事情都与operator new无关。之前就已经做完了。
1
2
3
4void operator delete(void *ptr)
{
free(ptr);
}
new[] delete[] ; new delete
1 | /* |
- new[] delete[]正常使用
- new[]
- 除了开辟对象内存之外,还会在栈顶方向(p-8)开辟一块内存用于记录对象个数。
- 用于释放数组时,得知需要调用几个对象的析构函数
- delete时会从那块内存(p-8)开始释放
- delete[]
- 会从对象栈顶方向4/8bytes开始。也会把那块内存的数据当作要析构的对象个数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19Test* p2 = new Test[5];
// 除了开辟对象内存之外,还会在栈顶方向(p-8)开辟一块内存用于记录对象个数。
// delete时也会连带释放那块内存(p-8)
cout << "p2:" << p2 << endl;
delete[] p2; // Test[0]对象析构, 直接free(p2)
operator new[] 0000021E55300DF0
Test()
Test()
Test()
Test()
Test()
p2:0000021E55300DF8
~Test()
~Test()
~Test()
~Test()
~Test()
operator delete[] 0000021E55300DF0
- 会从对象栈顶方向4/8bytes开始。也会把那块内存的数据当作要析构的对象个数
- new delete

1
2
3
4
5
6
7
8
9Test* p1 = new Test();
cout << "p1 : " << p1 << endl;
delete p1;
operator new : 000001A1BF04D6B0
Test()
p1 : 000001A1BF04D6B0
~Test()
operator delete : 000001A1BF04D6B0
- new delete[]混用后果

1 |
|
- new[] delete
- 只会调用一个对象的析构函数,并且用于记录对象个数的内存没有被释放


1
2
3
4
5
6
7
8
9
10
11
12
13Test* p2 = new Test[5];
cout << "p2:" << p2 << endl;
delete p2; // Test[0]对象析构, 直接free(p2)
operator new[] 00000299D1C59BA0
Test()
Test()
Test()
Test()
Test()
p2:00000299D1C59BA8
~Test()
operator delete : 00000299D1C59BA8
- 只会调用一个对象的析构函数,并且用于记录对象个数的内存没有被释放
对象池
- 简单来说:将对象所占的内存提前开辟出来,放到一个池子里面(链表维护),当需要构造对象的时候,就从池子里面取出内存来在那上面构造。

链式队列 + 内置对象池
1 |
|
- 新标准:静态常量可以在类里面初始化,不用在外面初始化。