ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

【C++】内存管理

【C++】内存管理

💗个人主页💗
⭐个人专栏——C++学习⭐
💫点击关注🤩一起学习C语言💯💫

目录

1. C/C++内存分布

2. C语言中动态内存管理方式

3. C++内存管理方式

 3.1 new/delete操作内置类型

3.2 new和delete操作自定义类型

4. operator new与operator delete函数


1. C/C++内存分布

C/C++程序的内存分布主要分为以下几个部分:

  1. 栈(Stack):栈是用来存储局部变量、函数参数等的内存区域。每当一个函数被调用时,都会分配一块栈帧来存储函数的局部变量和参数。栈是按照"先进后出"的原则进行管理,函数返回后,其所占用的栈帧会被释放。

  2. 堆(Heap):堆是用来动态分配内存的区域。在C/C++中,使用new/delete或malloc/free来进行堆内存的动态分配与释放。堆是按照"先进先出"的原则进行管理,需要手动释放分配的内存。

  3. 全局/静态存储区(Global/Static Storage):全局变量和静态变量都存储在这个区域中。全局变量在程序运行期间一直存在,静态变量的生命周期是整个程序运行期间。

  4. 常量存储区(Constant Storage):存储常量数据,例如字符串常量。这个区域的数据在程序运行期间不能被修改。

  5. 代码区(Code/Text):存储程序的机器指令。代码区是只读的,程序在运行时不能修改代码区的内容。

2. C语言中动态内存管理方式

在C语言中,动态内存管理主要通过以下几个函数来实现:

  1. malloc():用于分配指定大小的字节内存块。它接受一个参数,即所需内存的字节数,并返回一个指向分配内存的指针。

  2. calloc():用于分配指定数量和大小的连续内存块,并将每个字节都初始化为零。它接受两个参数,即所需内存块的数量和每个内存块的字节数,并返回一个指向分配内存的指针。

  3. realloc():用于重新分配已分配内存块的大小。它接受两个参数,即指向要重新分配大小的内存块的指针和新的内存块大小,并返回一个指向重新分配内存的指针。

  4. free():用于释放之前通过malloc()或calloc()分配的内存块。它接受一个参数,即要释放的内存块的指针。

#include <stdio.h>
#include <stdlib.h>int main() {int* numbers;// 分配存储5个整数的内存块numbers = (int*)malloc(5 * sizeof(int));if (numbers == NULL) {printf("内存分配失败\n");return 1;}// 向每个元素赋值for (int i = 0; i < 5; i++) {numbers[i] = i + 1;}// 打印每个元素的值for (int i = 0; i < 5; i++) {printf("%d ", numbers[i]);}printf("\n");// 重新分配内存块的大小为10个整数numbers = (int*)realloc(numbers, 10 * sizeof(int));if (numbers == NULL) {printf("内存重新分配失败\n");return 1;}// 向新增的元素赋值for (int i = 5; i < 10; i++) {numbers[i] = i + 1;}// 打印每个元素的值for (int i = 0; i < 10; i++) {printf("%d ", numbers[i]);}printf("\n");// 释放内存块free(numbers);return 0;
}

3. C++内存管理方式

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因 此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

  1. new/delete运算符:new运算符用于动态分配单个对象的内存,并返回指向该对象的指针,而delete运算符用于释放通过new分配的内存。相较于malloc/free函数,new和delete可以自动调用对象的构造函数和析构函数。

  2. new[]/delete[]运算符:new[]运算符用于动态分配对象数组的内存,并返回指向该数组的指针,而delete[]运算符用于释放通过new[]分配的内存。相较于malloc/free函数,new[]和delete[]可以自动调用每个对象的构造函数和析构函数。

 3.1 new/delete操作内置类型

1. new操作符:使用new操作符可以动态分配内置类型的内存空间,并返回指向该内存空间的指针。

int* p = new int; // 动态分配一个int类型的内存空间
float* q = new float; // 动态分配一个float类型的内存空间

2. delete操作符:使用delete操作符可以释放通过new操作符分配的内存空间,同时调用内置类型的析构函数进行资源的清理。

delete p; // 释放之前分配的int类型的内存空间
delete q; // 释放之前分配的float类型的内存空间

需要注意的是,对于内置类型,因为它们没有构造函数和析构函数,所以delete操作符只会释放内存空间,并不会进行其他操作。

而且,使用delete操作符释放的内存空间必须是通过new操作符进行分配的,否则可能导致未定义的行为。另外,动态分配的内置类型的内存空间一旦不再需要,应当及时释放,以避免内存泄漏和资源的浪费。

void Test()
{// 动态申请一个int类型的空间int* ptr4 = new int;// 动态申请一个int类型的空间并初始化为10int* ptr5 = new int(10);// 动态申请10个int类型的空间int* ptr6 = new int[3];delete ptr4;delete ptr5;delete[] ptr6;
}

3.2 new和delete操作自定义类型

class MyClass 
{
public:int* data;MyClass() {data = new int[5]; // 动态分配一个包含5个int元素的数组cout << "Constructor called" << endl;}~MyClass() {delete[] data; // 释放之前分配的数组内存空间cout << "Destructor called" << endl;}
};int main() 
{MyClass* obj = new MyClass(); // 动态分配一个MyClass对象的内存空间,并进行初始化// 使用动态分配的内存空间for (int i = 0; i < 5; i++) {obj->data[i] = i;cout << obj->data[i] << " ";}cout << endl;delete obj; // 释放之前分配的MyClass对象的内存空间,并调用析构函数return 0;
}

4. operator new与operator delete函数

operator new和operator delete是C++中的全局函数,用于自定义类对象的动态内存管理。new在底层调用operator new全局函数来申请空间,delete在底层通过 operator delete全局函数来释放空间。

 注意:operator new和operator delete不是对new和delete的重载,这是俩库函数

operator new函数用于分配内存空间:

void* operator new (std::size_t size);

它接受一个参数size,表示要分配的内存空间的大小,返回一个void指针,指向已分配的内存空间的起始地址。

operator delete函数用于释放内存空间:

void operator delete (void* ptr);

它接受一个参数ptr,表示要释放的内存空间的起始地址,无返回值。

这两个函数可以被重载,用于自定义内存分配和释放的行为。

class MyClass 
{
public:int data;MyClass(int d) : data(d) {std::cout << "Constructor called" << std::endl;}~MyClass() {std::cout << "Destructor called" << std::endl;}static void* operator new (size_t size) {std::cout << "Custom new operator called" << std::endl;void* ptr = std::malloc(size); // 使用malloc来分配内存空间if (!ptr) {throw std::bad_alloc(); // 内存分配失败,抛出异常}return ptr;}static void operator delete (void* ptr) {std::cout << "Custom delete operator called" << std::endl;std::free(ptr); // 使用free来释放内存空间}
};int main() 
{MyClass* obj = new MyClass(10);delete obj;return 0;
}

  

返回列表