5,411
社区成员




C++从入门到实战(十一)详细讲解C/C++语言中内存分布与C与C++内存管理对比
我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的C++知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12880513.html?spm=1001.2014.3001.5482
我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的C++知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12880513.html?spm=1001.2014.3001.5482https://blog.csdn.net/2402_83322742/category_12880513.html?spm=1001.2014.3001.5482
想象你去食堂打饭,餐盘是按顺序叠起来的:后放上去的餐盘先被拿走(后进先出)。
想象你去食堂打饭,餐盘是按顺序叠起来的:后放上去的餐盘先被拿走(后进先出)。
// 函数,函数代码存储在代码段
void func() {
// 局部变量,存储在栈上
int local_variable = 30;
std::cout << "Local variable: " << local_variable << std::endl;
}
// 调用函数,函数调用信息和局部变量会在栈上操作
int main()
{
func();
}
堆是用于动态分配内存的区域,程序可以在运行时从堆中请求和释放内存。
想象你去超市存包,储物柜可以按需申请:你觉得需要多大空间,就租多大的柜子,用完自己关门(释放),不关门的话柜子会一直被占着(内存泄漏)。
想象你去超市存包,储物柜可以按需申请:你觉得需要多大空间,就租多大的柜子,用完自己关门(释放),不关门的话柜子会一直被占着(内存泄漏)。
// 使用 malloc 分配内存
int *ptr_malloc = (int *)malloc(5 * sizeof(int));
// 使用 calloc 分配内存
int *ptr_calloc = (int *)calloc(5, sizeof(int));
// 使用 realloc 调整内存大小
ptr_malloc = (int *)realloc(ptr_malloc, 10 * sizeof(int));
// 释放内存
free(ptr_malloc);
free(ptr_calloc);
// 全局变量,存储在数据段
int global_variable = 10;
// 静态变量,存储在数据段
static int static_variable = 20;
void func() {
static int static_age = 18; // 静态局部变量,也存在数据段
}
我们来看下面的一段代码和相关问题
我们来看下面的一段代码和相关问题
int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
static int staticVar = 1;
int localVar = 1;
int num1[10] = { 1, 2, 3, 4 };
char char2[] = "abcd";
const char* pChar3 = "abcd";
int* ptr1 = (int*)malloc(sizeof(int) * 4);
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
free(ptr1);
free(ptr3);
}
int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
static int staticVar = 1;
int localVar = 1;
int num1[10] = { 1, 2, 3, 4 };
char char2[] = "abcd";
const char* pChar3 = "abcd";
int* ptr1 = (int*)malloc(sizeof(int) * 4);
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
free(ptr1);
free(ptr3);
}
在许多场景下,我们在编写代码时可能并不清楚程序运行时到底需要多少内存。
C语言提供了几个用于动态内存分配的函数,这些函数都在 <stdlib.h>
头文件中。
malloc
函数用于分配指定大小的内存块,其原型如下:
void* malloc(size_t size);
size
表示要分配的内存字节数,若分配成功,函数会返回一个指向该内存块起始位置的指针;若分配失败,则返回 NULL
。
下面是一个简单的示例:
#include <stdio.h>
#include <stdlib.h>
int main() {
// 分配一个能存储 5 个整数的内存块
int *ptr = (int *)malloc(5 * sizeof(int));
if (ptr == NULL) {
printf("内存分配失败\n");
return 1;
}
// 给分配的内存块赋值
for (int i = 0; i < 5; i++) {
ptr[i] = i;
}
// 打印内存块中的值
for (int i = 0; i < 5; i++) {
printf("%d ", ptr[i]);
}
printf("\n");
// 释放分配的内存
free(ptr);
return 0;
}
calloc
函数和 malloc
类似,不过它会把分配的内存初始化为 0。其原型如下:
void* calloc(size_t num, size_t size);
num
代表要分配的元素数量,size
表示每个元素的大小。
以下是使用 calloc
的示例:
#include <stdio.h>
#include <stdlib.h>
int main() {
// 分配一个能存储 5 个整数的内存块,并初始化为 0
int *ptr = (int *)calloc(5, sizeof(int));
if (ptr == NULL) {
printf("内存分配失败\n");
return 1;
}
// 打印内存块中的值
for (int i = 0; i < 5; i++) {
printf("%d ", ptr[i]);
}
printf("\n");
// 释放分配的内存
free(ptr);
return 0;
}
realloc
函数用于调整已分配内存块的大小。其原型如下:
void* realloc(void* ptr, size_t size);
ptr
是指向已分配内存块的指针,size
是新的内存块大小。若分配成功,函数会返回一个指向新内存块起始位置的指针;若失败,则返回 NULL
。
下面是使用 realloc
的示例:
#include <stdio.h>
#include <stdlib.h>
int main() {
// 分配一个能存储 5 个整数的内存块
int *ptr = (int *)malloc(5 * sizeof(int));
if (ptr == NULL) {
printf("内存分配失败\n");
return 1;
}
// 给分配的内存块赋值
for (int i = 0; i < 5; i++) {
ptr[i] = i;
}
// 调整内存块大小,使其能存储 10 个整数
ptr = (int *)realloc(ptr, 10 * sizeof(int));
if (ptr == NULL) {
printf("内存重新分配失败\n");
return 1;
}
// 给新分配的内存块赋值
for (int i = 5; i < 10; i++) {
ptr[i] = i;
}
// 打印内存块中的值
for (int i = 0; i < 10; i++) {
printf("%d ", ptr[i]);
}
printf("\n");
// 释放分配的内存
free(ptr);
return 0;
}
free
函数用于释放之前动态分配的内存。其原型如下:
void free(void* ptr);
ptr
是指向要释放的内存块的指针。一旦内存被释放,就不能再使用该指针访问这块内存了。
C++ 引入了new和delete运算符来进行动态内存分配和释放,它们能很好地解决 C 语言动态内存分配的部分问题
#include <iostream>
class MyClass {
public:
MyClass() {
std::cout << "构造函数被调用" << std::endl;
}
~MyClass() {
std::cout << "析构函数被调用" << std::endl;
}
};
int main() {
// 使用new分配内存并创建对象
MyClass *obj = new MyClass();
// 使用对象
// ...
// 使用delete释放内存
delete obj;
return 0;
}
#include <iostream>
class MyClass {
public:
MyClass() {
std::cout << "构造函数被调用" << std::endl;
}
~MyClass() {
std::cout << "析构函数被调用" << std::endl;
}
void printMessage() {
std::cout << "这是 MyClass 类对象的消息。" << std::endl;
}
};
int main() {
// 使用new[]分配数组内存
MyClass* arr = new MyClass[3];
// 使用数组,遍历数组并调用成员函数
for (int i = 0; i < 3; ++i) {
arr[i].printMessage();
}
// 使用delete[]释放数组内存
delete[] arr;
return 0;
}eturn 0;
}
C语言主要通过标准库函数来进行内存管理,核心函数有 malloc
、calloc
、realloc
和 free
。下面是这些函数的详细介绍:
malloc
**:用来分配指定大小的内存块,返回的是 void*
类型指针,需要手动进行类型转换。分配的内存内容是未初始化的。 calloc
**:功能和 malloc
类似,不过它会把分配的内存初始化为 0。 realloc
**:用于调整已经分配的内存块大小,可以扩大或缩小。 free
**:释放之前动态分配的内存,释放后该内存可被系统重新使用。 C++ 除了可以使用 C 语言的内存管理函数,还引入了 new
和 delete
运算符来进行动态内存管理。
new
**:用于动态分配内存,会自动调用对象的构造函数。对于单个对象使用 new
,对于数组使用 new[]
。 delete
**:用于释放 new
分配的内存,会自动调用对象的析构函数。对应 new
使用 delete
,对应 new[]
使用 delete[]
。 对比项 | C 语言 | C++ |
---|---|---|
内存分配函数/运算符 | malloc、calloc、realloc | new、new[] |
内存释放函数/运算符 | free | delete、delete[] |
类型安全性 | 返回void*指针,需要手动类型转换,类型安全性低 | 直接返回正确类型的指针,无需手动转换,类型安全性高 |
对象构造和析构 | 不支持自动调用构造和析构函数,需要手动管理 | 自动调用构造和析构函数,简化对象生命周期管理 |
异常处理 | 内存分配失败返回NULL,需手动检查 | 内存分配失败抛出std::bad_alloc异常,可使用try-catch处理 |
代码风格 | 面向过程,使用函数进行内存管理 | 面向对象,使用运算符进行内存管理,与类和对象结合紧密 |
对比项C 语言C++内存分配函数/运算符malloc 、calloc 、realloc``new 、new[] 内存释放函数/运算符free``delete 、delete[] 类型安全性返回 void* 指针,需要手动类型转换,类型安全性低直接返回正确类型的指针,无需手动转换,类型安全性高对象构造和析构不支持自动调用构造和析构函数,需要手动管理自动调用构造和析构函数,简化对象生命周期管理异常处理内存分配失败返回 NULL ,需手动检查内存分配失败抛出 std::bad_alloc 异常,可使用 try-catch 处理代码风格面向过程,使用函数进行内存管理面向对象,使用运算符进行内存管理,与类和对象结合紧密 |
以上就是这篇博客的全部内容,下一篇我们将继续探索C++中new和delete中更多精彩内容。
我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的C++知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12880513.html?spm=1001.2014.3001.5482
我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343
我的C++知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12880513.html?spm=1001.2014.3001.5482https://blog.csdn.net/2402_83322742/category_12880513.html?spm=1001.2014.3001.5482
| | 非常感谢您的阅读,喜欢的话记得三连哦 |
非常感谢您的阅读,喜欢的话记得三连哦
|
文章来源: https://blog.csdn.net/2402_83322742/article/details/147491593
版权声明: 本文为博主原创文章,遵循CC 4.0 BY-SA 知识共享协议,转载请附上原文出处链接和本声明。