操作系统
VirtualAlloc
需要程序员控制 内存空间分配 / 页调拨
HeapAlloc
程序员不需要处理 内存空间 页 问题 ,但需要自己创建堆 管理堆 销毁堆
进程创建时有默认堆 .
程序员可以HeapCreate创建自定义堆
GlobalAlloc / LocalAlloc
windows 16位操作系统用 ,已经废弃,但为兼容,仍可用
语言C++
malloc
提供动态内存分配
windows下
底层调用HeapAlloc
并不是在进程默认堆申请,而是在运行时库初始化创建的自定义堆分配
new 操作符
分两步:
1. 调用 operator new 分配内存
operator new 可重载 ,原型是 void * operator new(std::size_t ) throw(std::bad_alloc);
调用顺序:
要申请内存的数据类型 T 的内部 operator new
数据类型 T 所属命名空间的 operator new
全局 ::operator new
重载函数一般用 ::operator new / malloc 进行内存分配,加一些自定义内容?
windows vs ::operator new 的默认实现
Release 模式下调用 malloc
Debug 模式是调用 _malloc_dbg
2. 在1分配的内存上初始化对象
如果调用构造函数初始化对象失败,会自动调用 operator delete() 释放已经分配的内存
operator new 重载后,要重载对应的 operator delete,原型是 void operator delete(void *) throw();
其他:
带位置的 new 运算符(placement new)
语法: new (expression-list) new-type-id(optional-initializer-expression-list);
expression-list : 实参列表
new-type-id : 类型
optional-initializer-expression-list : 构造函数参数
这种形式的 new 运算符 首先调用 operator new(size_t,OtherTypeList) 来获取内存,
然后对该对象执行构造函数.
语义上包括四种使用情形:
1. 直接给出要构建对象的内存位置
2. 不抛出异常,如果内存分配失败返回空指针
3. 定制的/带其他参数的内存分配器
4. 用于调试目的,在构造函数调用失败时给出源文件名和行号
一般调用就是指第一种情形,用于在一块内存上调用 构造函数 (因为用户不能显示调用 构造函数 )
对应的 operator new(size_t,OtherTypeList) 由C++标准库提供实现 头文件<new>
inline void * operator new(std::size_t,void*__p)throw(){return __p;}
inline void * operator new[](std::size_t,void*__p)throw(){return __p;}
inline void operator delete(void *,void*) throw(){}
inline void operator delete[](void*,void*)throw(){}
因为通过 placement new 调用构造函数前,已经分配好了原始内存,
把内存地址通过 new (p) T(value) 传递给 operator new(size_t,void*)
带位置的 operator new只需要直接返回内存地址就可以
自定义参数的 operator new
operator new (size,Type1,Type2,...);
感觉 operator new(size) / operator new(size,void*) 都是自定义参数 operator new 的一种特殊情况
总的来说: new 运算符 会调用 operator new , 然后再调用构造函数
根据new 运算符不同的语法,调用不同的 operator new
1.普通的new运算符表达式 new Type(init value)
调用 void * operator new(std::size_t ) throw(std::bad_alloc);
2.带位置的new运算符表达式 new(ptr) Type(init value)
调用 void * operator new(std::size_t,void*__p) throw();
因为是在已经分配好的内容 ptr 上面进行构造,
所以标准库的 void * operator new(std::size_t,void*__p) 直接返回地址
3.自行定制参数的new运算符表达式 new (para) Type(init value)
调用 void * operator new(size, paraType)