c++的动态内存开辟
1.栈又叫堆栈是向下生长的,该位置存放非静态局部变量/函数参数/返回值/指针等等
2.堆用于程序运行时动态内存分配,堆是向上生长的
3.数据段--存放全局数据和静态数据
4.代码段--可执行的代码/只读常量
常见笔试题:
Static int s1=0;
Int s2=1;
Int f (int a)
{
Static int s3=3;
char* p1 = “abcd”;
char p2[] = “abcd”;
char* p3 = new char p3[10];
1.计算结果
sizeof(p1) 4 //计算一个指针的大小(4字节)
sizeof(p2) 5 //a b c d \0 5个字节
strlen(p1) 4 //strlen只找\0不看类型且不计算\0
strlen(p2) 4
2.下面代码是否可以编译通过?如果编不过?是哪句
*p1 = '1'; //XX因为指针解引用后是常量
*p2 = '1';
3.选择题
A. 栈 B.堆 C.静态区 D.常量区
s1在哪 静态区 s2在哪 静态区 s3在哪 静态区
p1在哪 栈 p2在哪 栈 p3在哪 栈
*p1在哪 常量区 *p2在哪 栈 *p3在哪 堆
一.c语言中的动态内存管理
1.malloc
c语言提供的malloc动态开辟空间函数:void* malloc(size_t size)
这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针.
如果开辟成功则返回指向这块空间的指针.
如果开辟失败则放回一个NULL指针(注:malloc的返回值一定要做检查)
返回值的类型是void*,所以malloc函数并不知道开辟空间的类型,具体在使用时由使用者自己决定
例:
int* p1=(int*)malloc(sizeof(int)*4)
如果malloc函数中的size=0这是标准为定义的,结果如何取决于编译器。
c语言提供了另一个函数free,专门用来做动态内存的释放和回收的,函数原型如:void free(void* ptr)
free函数用来释放动态开辟的内存:
1. 如果ptr指向的空间不是动态开辟的,那么free函数的行为是未定义的。
2. 如果ptr指针指向的是NULL,则free函数什么都不做。
3. malloc和free都在stdlib.h的头文件里
2.calloc
C语言还提供了一个函数叫calloc,calloc也可以进行动态开辟内存,函数原型如下:void* calloc(size_t num,size_t size)
函数的功能是为num个大小为size字节的元素开辟一块空间,并且把每个空间初始化为0
malloc与calloc的区别是calloc会在返回地址之前将开辟空间的每个字节初始化为0
例:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int* ptr = calloc(10, sizeof(int));
if (NULL != ptr)
{
//使用空间
}
free(ptr);
ptr = NULL;
return 0;
}
如果我们对申请的内存空间有初始化要求就用calloc
3.relloc
realloc函数可以做到对动态开辟空间大小的调整,函数原型如下:
void* realloc(void* ptr,size_t size)
.ptr是要调整内存的地址
.调整之后新大小
.返回值是调整之后内存的起始位置
.这个函数在调整原内存大小的基础上,还会将原来内存上的数据搬到新空间上.
.realloc调整空间大小有两种情况:
(1) 原来空间后面有足够大的内存空间,可以支持接在原来空间上扩容(这时不用搬运原来的数据)
(2) 原来空间后面没有足够大的内存空间,不可以支持接在原来空间上扩容.这时realloc会重新找一块足够大的空间,将原来数据搬到新空间上并扩容.ptr会改变,还要释放旧的空间(这时需要搬运原来的数据到新开的空间上)
二.c++语言中的动态内存管理
c++通过new和delete或者new[]和delete[]进行动态内存管理
new和delete动态管理对象
new[]和delete[]动态管理数组
注:一定要匹配使用new和delete;new不用计算申请空间的大小它会自动计算
例:
#include<iostream>
using namespace std;
int main()
{
int* p1 = new int;//只有类型
int* p2 = new int(3);//开了一个int大小的空间并给其赋值为3
int* p3 = new int[3];//申请了3个int大小的的空间
delete p1;
delete p2;
delete []p3;
return 0;
}
malloc和free只会开空间
new先开空间再调用构造函数;delete先调用析构函数在释放空间
典型错误示范:
面试题:
malloc/free和new/delete的区别和联系:
1.他们都是动态管理内存的入口
2.malloc/free是标准库函数,new/delete是c++的操作符
3.malloc/free只是动态分配/释放空间,new/delete除了会分配空间还会调用析构函数/释放空间还会调用析构函数进行初始化和清理工作.
4.malloc/free需要手动计算类型大小并且返回类型void*,new/delete会自动计算对应类型的大小并且返回对应类型.
c++的其他内存管理(placeman版本)
void* operator new(size_t size)
void operator delete(size_t size)
void* operator new[](size_t size)
void operator delete[](size_t size)
标准库函数operator new()和operator delete()容易让人误解,与其他的operator(例:operator=)不同,operator new()和operator delete()不是new和delete的重载,实际上我们不能重定义new和delete的表达式(因为new和delete是操作符)
总结:
1. operator new()/operator delete和()operator new[]()/operator delete[]()与malloc()/free()的用法是一样的
2. 它们只负责分配对象/释放对象的空间,不会调用构造和析构来进行初始化和清理工作
3. 实际上operator new()/operator delete()和operator new[]()/operator delete[]()只是malloc()/free()的一层浅封装
由此可得new做了2件事
1.调用operator new()来分配空间
2.调用构造函数来初始化对象
由此可得delete做了2件事
1.调用析构函数来清理空间
2.调用operator delete()来释放空间
由此可得new[N]做了2件事
1.调用operator new()来分配空间(每次开空间会多开4字节来记录N以便知道要调用多少次析构函数)
2.调用N次构造函数来初始化对象
由此可得delete[N]做了2件事
1.调用N次析构函数来清理空间
2.调用operator delete()来释放空间
例: