在计算机的程序内,有不同的内存分区,内存分区是为了有效管理和利用计算机的内存资源而进行的划分,也是因为不同的数据有不同的存储需求,各区域需要满足不同的需求。
我们先大致了解一下常见到的几个内存分区(静态区,常量区,堆区,栈区):
静态区:
静态区(也称为数据段)是程序的一部分,用于存储全局变量和静态变量。在C/C++中,静态变量包括全局静态变量和局部静态变量。
全局静态变量存储在静态区中,并且在整个程序的执行期间都存在。它们在程序启动时被初始化,并且只被分配一次内存。
局部静态变量也存储在静态区中,但是它们只在其所在函数第一次执行时被初始化,并且在函数执行过程中保持其值。与自动变量不同,局部静态变量的生命周期超出函数的作用域。
常量区:
常量区(也称为代码段或只读数据段)是存储程序中的常量数据的一部分。在常见的C/C++实现中,常量区通常位于程序的可执行文件中,并且在程序运行时是只读的,不允许修改。
常量区包括以下类型的数据:
需要注意的是,常量区中的数据是只读的,因此在程序运行过程中不能修改这些数据的值。
但是,对于指针变量(如指向常量区的指针),可以通过改变指针的指向来间接修改常量区中的数据。不过,这样的操作是不安全的,可能会导致未定义的行为,因此应该避免这样做。
总结起来,常量区存储程序中的常量数据,包括字符串常量、全局常量和静态常量。它是只读的,在程序运行时不能修改。
堆区:
堆区是用于动态内存分配的一部分内存空间。它在程序运行时动态地分配和释放内存,用于存储程序中的动态对象。
在C/C++中,通过调用malloc、calloc、realloc等函数来在堆区分配内存。这些函数返回指向分配内存的指针。分配的内存可以使用指针进行访问,并且在不再需要时需要手动调用free函数来释放内存,以防止内存泄漏。
堆区的特点如下:
栈区:
栈区是一种用于存储局部变量和函数调用信息的内存空间,它的管理方式类似于一个堆叠。
在函数被调用时,函数的参数和局部变量将会被压入栈中。当函数执行完毕时,这些变量将会从栈中弹出。
栈区的特点如下:
在C语言中我们常用malloc、calloc和realloc函数来进行动态内存管理,这种内存管理方式在C++中可以继续使用,但有些地方就无能为力,比如说malloc解决不了动态申请的自定义类型的初始化问题,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
new是C++的关键字,用于在堆上动态分配内存,它可以调用适当的构造函数初始化分配的内存,并返回指向该内存的指针。也就是说的new会做两件事情,一是开空间而是调用构造函数
new的基本语法如下:
new 类型名;
其中类型名可以是任何C++数据类型或用户自定义类型。例如,要分配一个整数变量,可以使用以下代码:
int* p = new int;
也可以使用new来分配数组,例如:
int* a = new int[10];
这将分配包含10个整数的数组,并将第一个元素的地址赋给指针变量a。
delete 是 C++ 中用于释放通过 new 操作符分配的动态内存的操作符。它的基本语法如下:
delete 指针;
其中,指针是通过 new 操作符返回的指向动态内存的指针。当 delete 操作符被执行时,它会释放指针所指向的动态内存,并调用相应对象的析构函数进行资源清理。
例如,如果通过 new 操作符分配了一个整数对象的内存,可以使用 delete 操作符释放该内存,如下所示:
int* ptr = new int;
// 使用指针进行一些操作
delete ptr;
同样,如果通过 new 操作符分配了一个自定义类对象的内存,也可以使用 delete 操作符释放该内存,这时delete会调用析构函数,如下所示:
MyClass* obj = new MyClass();
// 使用对象进行一些操作
delete obj;
需要注意的是,delete 只能用于释放通过 new 操作符分配的内存。对于栈上或静态内存中的对象,不应该使用 delete 进行释放。
另外,在delete释放指针之后,应该将指针设置为 nullptr,以避免出现悬空指针的情况。例如:
delete ptr;
ptr = nullptr;
申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用
new[]和delete[],注意:匹配起来使用。
总之,new是C++中用于在堆上动态分配内存的关键字,它可以调用构造函数初始化分配的内存,并返回指向该内存的指针。与malloc相比,new更加灵活,能够支持对象的构造和析构,不需要手动计算分配的内存大小。delete 是 C++ 中用于释放通过 new 操作符分配的动态内存的操作符。需要配套new进行使用。