malloc/free 和 new/delete
malloc和new应当是都在堆上分配内存, 但有一点区别
mallloc & free
从malloc工作原理来看, 就仅仅是分配一块大小合适的地方…以前笔记也有记录过, 最初是从顶块上割下来一块用, free掉后会进入fast bin, 或者其他的bin链表里, 再后来malloc的话, 根据大小, 从不同的bin上取下来, 返回的是User Data的起始地址, 不包括chunk header, 很纯粹, 只是分配空间给你, 没有初始化还是其他什么的内容
从语言层面来看, malloc返回的是void *
的类型, 所以在使用的时候要强制类型转换一下
对了, 实际使用过程中, malloc之后应当检测一下, 结果是不是NULL, 然后再使用(我下面没写)
free的话就是…emmmmm, 把分出去的chunk给收回来, 放到空闲链表里…其实就是增加了fd
, bk
, 指针
我写了一个蹩脚的链表. 然后怀疑人生中
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node {
struct node * next;
int val;
}Node;
int main() {
Node * list = (Node *)malloc(sizeof(Node));
list -> val = 111;
list -> next = (Node *)malloc(sizeof(Node));
list -> next -> val = 222;
list -> next -> next = NULL;
Node * ptr = list;
while(ptr != NULL) {
printf("%d\n", ptr -> val);
ptr = ptr -> next;
}
printf("print done\n");
ptr = list;
while(ptr != NULL) {
Node * temptr = ptr;
ptr = ptr -> next;
free(temptr);
}
printf("free done\n");
return 0;
}
new & delete
这个其实我不太熟悉, 因为我不太会oop, 所以很少用
只知道new是C++的一个操作符…
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
class A {
private:
static int num;
public:
int a;
A() {num++; puts("num++");}
A(int _a):a(_a * _a) {num++; puts("num++");}
void b() {printf("[*]%d a: %d", num, a);}
};
int A::num = 0;
int main() {
A * a1 = new A;
a1 -> b();
puts("");
A * a2 = new A();
a2 -> b();
puts("");
A a3;
a3.b();
puts("");
A * a4 = (A * )malloc(sizeof(A));
a4 -> b();
return 0;
}
/*
num++
[*]1 a: 0
num++
[*]2 a: 0
num++
[*]3 a: 2
[*]3 a: 0
*/
首先有个重要的问题就是, 类内的静态成员变量要在类外进行定义…不然就会出现未定义的引用..就像我这里写的那个int A::num = 0
类内部写的静态成员, 相当于是只做了一个申明, 只是有了一个scope, 但要使用(存储)的话必须要在类外定义一下
静态其实是讲与程序有着相同的生命周期…所以静态变量即便是局部的…也只是作用域在局部…但却是一直存在的, 所以也只会经历一次初始化, 从存储上讲的话, 静态变量和全局变量是一样的…未初始化的在bss, 初始化的在data
跑题了….从上面就可以看出来的new和malloc的区别
- malloc返回的指针是
void *
的, 需要强制转化, 而new的话返回的就不需要了 - malloc分配的大小需要自己定, new的话不需要
- malloc不会调用构造函数…这个从最后一个没有
num++
可以看出来,当然简单数据类型的话new也不调用 - new分配失败好像会触发异常, 所以不能通过是否返回NULL来判断分配成功与否
所以相应的delete不光是会回收空间, 可能还会调用析构函数
据说是new分三个过程
- 调用operator new(size), 比如 new int, 差不多汇编是这样子
push 4 call operator new(size) add esp, 4
- 在分配的内存空间上, 调用构造函数(基本类型没有在这个操作)
- 转换指针类型??? (这个我也不太确定)
这里看到上面四个生成类的方法, 还想讲几点
有括号和没括号的区别
- 对于内置类型, 比如int
new int // 不会初始化 new int() //会初始化为0
- 对于类
- 没括号是默认初始化
- 有括号是值初始化
结论: 我还是加括号吧, 这个我还是不太清楚
用new和不用new的区别
new底下调用的是malloc, 是在堆上分配内存
不new的话…就是在栈上了呗…
另外, 不new的话, 也有隐和显两种写法
A a = A(2);
A a(2);
差不多就这样子了