1.c/c++的内存分布
在c/c++中内存一般是分为栈区,堆区,静态区,常量区,以及寄存器。其中栈区是用来创建函数栈帧的,我们动态开辟的空间(比如malloc,calloc,realloc)就是在堆区上的。静态区主要存储static修饰的变量,全局变量在程序启动时分配内存,在程序结束时释放。常量区主要存储const修饰的对象和字符串常数。
2.c++内存管理方式
众所周知C语言的内存管理方式是malloc/calloc/realloc/free,但在c++中一般使用的是new/delete。c++申请空间的一般形式是:类型名 变量名 = new 类型名() ,其中()是用来初始化变量的可写可不写。()也可以换成[]一般是用来申请多个空间,如果想要对[]中的内容进行初始化则可以在[]后加{}在{}内进行初始化。delete一般用来释放空间如果变量申请空间时使用了[]则在释放时要在delete后加上[]。如下。
#include<iostream>
using namespace std;
int main() {
int* a = new int;
int* b = new int(1);
int* c = new int[10];
int* d = new int[10] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
delete a;
delete b;
delete[] c;
delete[] d;
}
3.new/delete对自定义类型操作
刚刚说过new可以对变量进行初始化,对于内置类型进行初始化是在分配空间时进行的,但对自定义类型比如类类型就要调用类的构造函数了。delete在销毁时与不同之处在于如果是自定义类型delete会调用析构函数再释放空间。简单来说new是先申请空间再调用构造,delete是先析构再释放空间。
#include<iostream>
using namespace std;
class A {
public:
A(int x = 1)
:a(x){
cout << "A(int x = 1)" << endl;
}
~A() {
a = 0;
cout << "~A()" << endl;
}
private:
int a;
};
int main() {
A* x = new A(1);
delete x;
}

4.operator new与operator delete
operator new与operator delete算是对malloc/free的封装。标准并没有强制规定 operator new/delete 必须基于 malloc/free 来实现,只是大多数编译器是这样做的。new 表达式:首先调用 operator new 分配内存,接着调用对象的构造函数来初始化这块内存。delete 表达式:先调用对象的析构函数,然后调用 operator delete 释放内存。正常new时如果出错operator new会抛出异常。在分配多个空间时则会调用operator new[],operator new[]一般会多开辟4个字节的空间用来存储开辟空间的数量。目的是确定调用几次构造和析构函数。
5.定位new表达式
定位new表达式是在已分配空间中调用构造函数来初始化一个对象,表达式为new(指针)构造函数(如果构造函数有参记得传参)。这样做可以在申请空间后再初始化可以让new不抛错。但实际上很少有这样的需求。
6.new/delete和malloc/free的区别
malloc/free 和 new/delete 的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是: malloc 和 free 是函数,new 和 delete 是操作符。 malloc 申请的空间不会初始化,new 可以初始化 malloc 申请空间时,需要手动计算空间大小并传递,new 只需在其后跟上空间的类型即可,如果是多个对象,[] 中指定对象个数即可 malloc 的返回值为 void*,在使用时必须强转,new 不需要,因为 new 后跟的是空间的类型 malloc 申请空间失败时,返回的是 NULL,因此使用时必须判空,new 不需要,但是 new 需要捕获异常 申请自定义类型对象时,malloc/free 只会开辟空间,不会调用构造函数与析构函数,而 new 在申请空间后会调用构造函数完成对象的初始化,delete 在释放空间前会调用析构函数完成空间中资源的清理释放
4273

被折叠的 条评论
为什么被折叠?



