C/C++内存分布
C/C++内存区域划分
文章图片
数据段的大小是根据VS2013开的全局数组测出来的,可能不是很准各区域功能
- 内核:操作系统使用的空间,用户不能读写
- 栈:局部变量,局部数组等都在栈,栈向下生长,即栈往低地址生长
const修饰的变量得分情况,还得分c和c++
参考这个大佬的博客const修饰的变量的存储位置
- 内存映射段:与系统有关,待了解
- 数据段(静态区):存储全局数据和静态数据
- 代码段(常量区):可执行代码(二进制指令)和只读常量
const修饰的是变量,所以不叫只读常量
随笔记录:0x7fffffff相当于INT_MAX的一半,例子
//变量在内存里的分布demo
#include
#include
using namespace std;
//variable的意思是变量,var是variable的简称
int global_var;
//数据段
static int static_global_var;
//数据段(静态区)
int main()
{
static int static_var;
//数据段
int local_var;
//栈 char a[10]="abcd";
//a在栈,数据也都在栈
*a;
//*a在栈
char* b = "abcd";
//b在栈,数据在代码区(常量区)
*b;
//*b在代码区 int* ptr = (int*)malloc(10);
//ptr在栈,开辟的空间在堆
*ptr;
//堆 return 0;
}
文章图片
C语言管理内存的方式
通过malloc、calloc、realloc、free
- malloc在堆上开辟空间,但是不初始化
- calloc==malloc+初始化,不仅会开空间还会初始化
- realloc,扩容+拷贝数据,如果空间不够需要扩容时就用realloc
- free释放空间,防止内存泄漏等问题
初识
//初始new delete
int main()
{
//C
int* ptr = (int*)malloc(sizeof(int));
free(ptr);
//C++
int* pa = new int;
delete pa;
return 0;
}
文章图片
概念
- 什么是new?
malloc是一个库函数
- 什么是delete?
类比free简单用法
//new、delete对于自定义类型调用构造、析构函数demo
class A
{
public:
A()
{
cout << "A()" << endl;
}
~A()
{
cout << "~A()" << endl;
}
};
int main()
{
A* pa1 = (A*)malloc(sizeof(A));
free(pa1);
cout << "malloc 和 free结束" << endl;
cout << endl;
A* pa2 = new A;
delete pa2;
cout << "new 和 delete结束" << endl;
return 0;
}
文章图片
从这也可以看出new和malloc的区别之一就是会不会调用构造函数,delete和free的区别之一就是不会调用析构函数
//new、delete内置类型数组和自定义类型数组
class A
{
public:
A(){}
A(int){}};
int main()
{
int* ptr = new int[10];
//开一个十个int大小的数组
delete[] ptr;
int* ptr2 = new int(5);
//开一个int大小的空间并且初始化为5
delete ptr2;
A* pa = new A[10];
//开一个十个A类型大小的数组,调用十次构造函数
delete[] pa;
A* pa2 = new A(5);
//会调用构造函数A(int)进行构造
delete pa2;
return 0;
}
文章图片
汇编证明new的过程调用了构造函数
文章图片
原则上new和delete成对使用,如果new和free配对使用,可能造成程序崩溃.
- 我们之前有了malloc和free来动态开辟空间,那为什么会出现new和delete?
###malloc、free和new、delete的区别
- malloc和free是函数,new和delete是操作符
- malloc不能对申请的空间初始化,new可以
- 针对自定义类型,delete可以调用析构函数完成对象内资源的清理,而free不行
- 用法上,malloc需要强转类型和计算类型大小,new不需要
- 对于错误的处理,malloc开辟失败返回空指针,而new直接抛出异常,需要对异常进行捕获
- operator new和operator delete是两个全局函数,而不是运算符重载
- new底层调用operator new开辟空间
- delete底层调用operator new释放空间
- void* operator new(size_t)和void operator delete(void* )
这段源码在new.cpp中
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{// try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{// report no memory
_THROW_NCEE(_XSTD bad_alloc, );
}return (p);
}
由源码可以看出,如果返回的是空指针,则抛出异常
由源码可见operator new也不过是对malloc进行了封装operator delete源码 这块没找到源码,找到的资料大概意思是:operator delete这个函数相当于对free进行了封装
【C++学习笔记|C++内存管理笔记】如果有大佬知道这个函数的源码位置,麻烦告诉我一下
随笔记录:operator delete释放空指针不报错operator new和operate delete专属类重载
文章图片
//类内重载operator new和operate delete的demo
#include
using namespace std;
class A
{
public:
void* operator new(size_t n)
{
cout << "void* operator new(size_t n)" << endl;
return nullptr;
}
void operator delete(void* p)
{
cout << "void operator delete(void* p)" << endl;
}
};
int main()
{
A* pa=new A;
delete pa;
return 0;
}
文章图片
new和delete原理
new:调用operaotr new函数开辟空间,再在空间上调用构造函数
delete:调用析构函数释放空间内的资源,再调用operator delete函数释放对象对象的空间
new T[N]:调用operator new开辟空间,再调用N次构造函数
delete[]:先执行N次析构函数,再把开辟的对象空间释放掉
placement new
引论 我们说new与malloc的不同点之一是new会调用构造函数
回顾一下之前调用构造函数的情形:定义对象或者new一个对象时都会调用构造函数,且是自动调用的
如果我们要对malloc出来的空间手动调用构造函数应该怎么办?
此时就需要placement new,即定位new表达式
用法 placement new也叫定位new表达式
作用:在已分配的空间调用构造函数初始化对象
比如我们malloc后调用构造函数初始化对象使用场景:内存池等
用法:new(指向对象的指针)类名(构造函数参数)
//定位new表达式的用法demo
class A
{
public:
A()
{
cout << "A()"<~A();
free(pa);
return 0;
}
文章图片
总结
- 内存区域的划分,即每块区域可以放什么数据(语言层面)
- new和delete和malloc和free的差别主要在于对自定义类型的处理上,这个处理包括开辟成功和开辟失败
- new和delete的底层依赖于operator new()和operator delete()两个全局函数
- operator new()和operator delete()两个全局函数可以理解为是对malloc和free进行了一层封装
- 定位new表达式可以手动调用自定义类型的构造函数
- C++更加推荐使用new和delete进行内存管理
推荐阅读
- c++|C++读书笔记(模板)
- C++|C++学习笔记9 模板
- 程序人生|被裁了,39 岁阿里 P9,攒下 1.5 亿....
- python|编程开源_开源社区在编程中的方式和方式
- java人生|女程序员晒出工资条(工资高归高,但是感觉自己1年老了10岁)
- java|28 岁的我裸辞了,四年 Java 老鸟,只因薪水被应届生倒挂,在闭关三个月后拿到阿里 Offer
- python|python学习笔记——day05
- 蓝桥杯真题题解|蓝桥杯2015初赛-奖券数目-枚举
- ui|广工工作室各方向学习指南