admin管理员组

文章数量:1794759

【C++初阶】:C&C++内存管理

1、1.C/C++内存分布

我们先来看下面的一段代码和相关问题

代码语言:javascript代码运行次数:0运行复制
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);
}

1. 选择题:
  选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)
  globalVar在哪里?__C__  staticGlobalVar在哪里?__C__
  staticVar在哪里?__C__  localVar在哪里?__A__
  num1 在哪里?__A__
  
  分析:
  globalVar全局变量在数据段 staticGlobalVar静态全局变量在静态区
  staticVar静态局部变量在静态区  localVar局部变量在栈区
  num1局部变量在栈区

  char2在哪里?__A__  *char2在哪里?__A__
  pChar3在哪里?__A__   *pChar3在哪里?__D__
  ptr1在哪里?__A__    *ptr1在哪里?__B__
  
  分析:
  char2局部变量在栈区  
  char2是一个数组,把后面常量串拷贝过来到数组中,数组在栈上,所以*char2在栈上
  pChar3局部变量在栈区   *pChar3得到的是字符串常量字符在代码段
  ptr1局部变量在栈区     *ptr1得到的是动态申请空间的数据

【说明】 1、栈又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的,栈可以通过函数_alloca进行动态分配,不过注意,所分配空间不能通过free或delete进行释放,频繁的申请空间和释放空间,容易造成内存碎片,甚至内存泄漏,栈区由于是自动管理,不存在此问题。 2、内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。(现在只需要了解, 后面在linux中会提到) 3、堆用于程序运行时动态内存分配,堆是可以上增长的。堆无法静态分配,只能动态分配 4、数据段–存储全局数据和静态数据。 5、代码段–可执行的代码/只读常量。


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

方式:malloc/calloc/realloc/free

代码语言:javascript代码运行次数:0运行复制
void Test()
{
	int* p1 = (int*)malloc(sizeof(int));
	free(p1);
	// 1.malloc/calloc/realloc的区别是什么?
	int* p2 = (int*)calloc(4, sizeof(int));
	int* p3 = (int*)realloc(p2, sizeof(int) * 10);
	// 这里需要free(p2)吗?
	free(p3);
}

malloc/calloc/realloc的区别? 三者都是分配内存,都是stdlib.h库里的函数,但是也存在一些差异。 (1)malloc函数。其原型void *malloc(unsigned int num_bytes); num_byte为要申请的空间大小,需要我们手动的去计算,如int *p = (int*) malloc( 20*sizeof(int)),如果编译器默认int为4字节存储的话,那么计算结果是80Byte,一次申请一个80Byte的连续空间,并将空间基地址强制转换为int类型,赋值给指针p,此时申请的内存值是不确定的。 (2)calloc函数,其原型void *calloc(size_t n, size_t size); 其比malloc函数多一个参数,并不需要人为的计算空间的大小,比如如果他要申请20个int类型空间,会int *p = (int *)calloc(20, sizeof(int)),这样就省去了人为空间计算的麻烦。但这并不是他们之间最重要的区别,malloc申请后空间的值是随机的,并没有进行初始化,而calloc却在申请后,对空间逐一进行初始化,并设置值为0; 既然calloc不需要计算空间并且可以直接初始化内存避免错误,那为什么不直接使用calloc函数,那要malloc要什么用呢? 实际上,任何事物都有两面性,有好的一面,必然存在不好的地方。这就是效率。calloc函数由于给每一个空间都要初始化值,那必然效率较malloc要低,并且现实世界,很多情况的空间申请是不需要初始值的,这也就是为什么许多初学者更多的接触malloc函数的原因。 (3)realloc函数和上面两个有本质的区别,其原型void realloc(void *ptr, size_t new_Size) 用于对动态内存进行扩容(及已申请的动态空间不够使用,需要进行空间扩容操作,ptr为指向原来空间基址的指针, new_size为接下来需要扩充容量的大小。


3、C++内存管理方式

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

本文标签: C初阶CampC内存管理