operator new() 和 malloc()

operator new()就是调用malloc来申请内存空间
所有的分配内存操作最终都将落在 malloc 上。malloc分配的实际内存要比申请的内存大,因为有附加信息,附加信息一般是固定的
allocators(VC6 BC5 G2.9 G4.9)
-
VC6版本

-
BC5版本

- G2.9版本

G2.9虽然定义了和其他版本分配器类似的<defalloc.h>,但是未使用它。G2.9使用了一种改进的allocator,即<stl_alloc.h>
allocator的目标:尽量减少malloc的次数、减少额外开销。<stl_alloc.h>能够减少额外开销:

减少额外开销:
额外开销来自于对该块空间的大小等的说明(Cookie),G2.9通过以下方法节省额外开销:
G2.9实际上的allocator是维护n个链表,每一个链表负责某一个特定大小的区块,如第1个链表1个字节的分配,第2个负责2个字节的分配,第3个负责3个字节的分配…没有时再去和操作系统申请并切割
同一个链表上的内存块可以省掉一些额外开销,如大小等信息就不必再加上
- G4.9版本(最新版本)
G4.9又摒弃了G2.9的设计,用了无特殊设计的VC6模式,如下

但G2.9版本也被保留了

allocator使用方法
int main() {
std::allocator<std::string> alloc; // 可以分配string的allocator对象
int n{
5};
auto const p = alloc.allocate(n); // 分配n个未初始化的string
auto q = p;
alloc.construct(q++); // *q为空字符串
alloc.construct(q++, 10, 'o'); // *q为cccccccccc
alloc.construct(q++, "hello"); // *q为hello
std::cout << *p << std::endl; // 正确:使用string的输出运算符
//std::cout << *q << std::endl; // 错误:q指向未构造的内存
std::cout << p[0] << std::endl;
std::cout << p[1] << std::endl;
std::cout << p[2] << std::endl;
while (q != p) {
alloc.destroy(--q); // 释放我们真正构造的string
}
alloc.deallocate(p, n);
return 0;
}
allocator源码详解
源文件结构
这里面还有很多底层函数没找到实现在哪里,只能先看大概
1. 在QT5.8中,vector定义如下
template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class vector : protected _Vector_base<_Tp, _Alloc>{
}
template<typename _Tp, typename _Alloc>
struct _Vector_base{
}
默认使用std::allocator分配器
2. allocator结构说明

(1)以qt5.8的allocator.h为例,最上一层定义了多个allocator,其中一个如下

(2)可以看到上面的allocator类中没有标准规定的deallocator等函数。但是它继承了基类**__allocator_base**,而该基类出现在c++allocator.h中,如下:
template<typename _Tp>
using __allocator_base = __gnu_cxx::new_allocator<_Tp>;
(3)进一步找到**<new_allocator.h>**文件,可以发现里面定义了allocator所需要的所有必须类,包括在deallocator在内。___gnu_cxx::new_allocator<_Tp>是大部分编译器实现allocator的最底层

allocator基类:new_allocator
参考:https://zhuanlan.zhihu.com/p/354191253
https://blog.csdn.net/mei_true/article/details/113951160
c++默认的内存分配器继承于___gnu_cxx::new_allocator<_Tp>,它有两个任务
- 分配对象内存、初始化对象
- 析构对象、释放对象内存
源码如下:
//使用std中size_t和ptrdiff_t定义,为了程序的可移值性适应不同平台
//size_t表示unsigned类型,ptrdiff_t保存两个指针相减的结果
using std::size_t;
using std::ptrdiff_t;
//1. 定义new_allocator模板
template<typename _Tp>
class new_allocator{
public:
typedef size_t size_type;//类型定义,__allocator_traits中介绍
typedef ptrdiff_t difference_type;//元素之间的距离
typedef _Tp* pointer;//指针类型
typedef const _Tp* const_pointer;
typedef _Tp& reference;//左值引用类型(左值就是非临时变量)
typedef const _Tp& const_reference;
typedef _Tp value_type;//元素类型
//2. rebind,结构体模板(重要函数)
template<typename _Tp1>
struct rebind{
typedef new_allocator<_Tp1> other;
};
//3. 检测是否支持C++11标准;里面的变量含义将在后面内存学习中详细解答
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2103. propagate_on_container_move_assignment
typedef std::true_type propagate_on_container_move_assignme

本文深入探讨C++中的内存管理机制,特别是allocator的概念及其在STL容器中的应用。介绍了operator new与malloc的区别,以及allocator如何通过减少malloc调用次数和额外开销来优化内存分配。

2844

被折叠的 条评论
为什么被折叠?



