您的位置:首页 > 财经 > 产业 > 3d网页游戏排行榜前十名_交互设计就业前景_郑州网站制作工具_在线识图

3d网页游戏排行榜前十名_交互设计就业前景_郑州网站制作工具_在线识图

2025/3/13 18:14:12 来源:https://blog.csdn.net/yishaobai/article/details/146124212  浏览:    关键词:3d网页游戏排行榜前十名_交互设计就业前景_郑州网站制作工具_在线识图
3d网页游戏排行榜前十名_交互设计就业前景_郑州网站制作工具_在线识图

深入理解C/C++内存管理

  • 引言
  • 1、内存布局基础
  • 2、动态内存管理
    • 2.1 C风格内存管理
    • 2.2 C++运算符`new`/`delete`
    • 2.3 匹配使用问题
  • 3、区别

引言

在系统级编程中,C/C++因其直接操作内存的能力而备受青睐,但这也意味着开发者需要承担内存管理的责任。内存泄露、段错误(Segmentation Fault)和悬空指针等问题往往源于对内存管理机制理解不足。本文将深入探讨C/C++内存管理的关键机制、常见陷阱等。

1、内存布局基础

C/C++程序运行时内存分为以下区域:

  1. 栈(Stack)
    • 存储局部变量、函数参数。
    • 自动管理,采用后进先出(LIFO)模式,分配/回收由编译器隐式完成。
    • 容量有限,过度使用(例如无限递归)导致栈溢出(Stack Overflow)。

后进先出

  1. 堆(Heap)
    • 动态分配,需手动管理(malloc/freenew/delete)。
    • 容量较大但分配效率低于栈。
    • 内存泄露高发区。
  2. 静态区
    • 存储全局变量、静态变量(static)。
    • 生命周期持续至程序结束。
  3. 代码区
    • 存储可执行指令。

2、动态内存管理

2.1 C风格内存管理

#include <stdio.h>
#include <stdlib.h>int main(void) {int *array = (int *)malloc(sizeof(int) * 10);if (array == NULL) {perror("malloc");}free(array);return 0;
}
  • malloc/calloc/realloc分配内存失败会返回NULL
  • 陷阱
    • 忘记free导致内存泄露。
    • 重复释放(Double Free)。
    • 访问已释放内存(悬空指针)。
    • 需要手动计算分配空间大小,结构体类型容易疏忽导致分配内存大小错误。

2.2 C++运算符new/delete

#include <iostream>int main() {int* a = new int(10); // 分配空间并初始化std::cout << *a << std::endl;delete a;return 0;
}
#include <iostream>int main() {int* a = new int[10]; // 分配40字节大小空间for (int i = 0; i < 10; i++) {a[i] = i;}for (int i = 0; i < 10; i++) {std::cout << a[i] << std::endl;}delete[] a;return 0;
}
  • 优势
    • 自动计算大小,类型安全,无需显式类型转换。
    • 调用构造函数/析构函数。
#include <iostream>class Stack {
public:Stack(int n = 5) {data_ = new int[n];top_ = 0;capacity_ = n;}~Stack() {delete[] data_;top_ = capacity_ = 0;}
private:int* data_;int top_;int capacity_;
};int main() {Stack* p_stack = new Stack(10);delete p_stack;return 0;
}

new会调用构造函数

调用构造函数

#include <iostream>class Stack {
public:Stack(int n = 5) {data_ = new int[n];top_ = 0;capacity_ = n;}~Stack() {delete[] data_;top_ = capacity_ = 0;}
private:int* data_;int top_;int capacity_;
};int main() {Stack* p_stack = (Stack*)malloc(sizeof(Stack));free(p_stack);return 0;
}

malloc不会调用构造函数

  • 因此,new/delete非常适用于自定义类型动态开辟空间,可以完成类的初始化和释放类内动态开辟资源。

2.3 匹配使用问题

  • malloc/free成对出现不必多说,new申请数组时,需要使用delete[]来搭配使用,如果单纯使用delete会发生什么现象呢?
class A {
public:A(int a = 0): a_(a) {}
private:int a_;
};int main() {A* pa = new A[10];delete pa;return 0;
}
  • 以上代码会正常运行,这样看来使用delete来释放指向连续空间的指针也是可以的,但真的是这样吗?
  • 让我们将代码变换一下:
class A {
public:A(int a = 0): a_(a) {}~A() {}
private:int a_;
};int main() {A* pa = new A[10];delete pa;return 0;
}

报错信息

  • 我们发现只是显式编写了析构函数,程序就报错了。
  • 当我们显示定义了析构函数(即使它是空的),编译器对对象销毁的要求更加严格,错误地用delete释放new[]分配的内存会被明确指出。
  • 因此在使用上,一定要匹配使用。

3、区别

  1. malloc分配空间不会初始化,new可以初始化。
  2. 在申请自定义类型空间时,malloc/free只申请/释放空间,new/delete会调用自定义类型的构造/析构函数,完成对象的初始化和释放资源。
  3. malloc事情空间时需要手动计算空间大小,new后面只需要接类型即可,申请连续空间也只需要使用[n]指明申请数据量即可。
  4. malloc申请空间失败返回NULLnew申请空间失败会抛异常。
  5. malloc的返回值是void*,因此需要强制类型转换;new不需要。
  6. malloc/free是函数,new/delete是操作符。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com