我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++详细讲解内存管理工具primitives

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++详细讲解内存管理工具primitives

primitives

分配释放属于是否可重载
malloc()free()C不可
newdeleteC++表达式不可
::operator new()::operator delete()C++函数
allocator::allocate()allocator::deallocate()C++标准库可自由设计搭配容器

new 和 delete

C/C++中的new和delete的实现过程

operator new():第一个参数表示大小,第二个参数表示保证这个函数不抛出异常。

注意:构造函数不能直接调用,而析构函数可以直接调用。

new[] 与 delete[] 要搭配使用,未搭配使用可能会内存泄漏,泄露的是指针所指向的地方。

析构的时候次序会逆反。

对于 析构函数 没有意义,new[] 是否对应 delete[] 不重要,但是 当析构函数有意义时,必须对应。

placement new

placement new 允许我们将对象建构在一个已经分配的内存中。并且没有对应的placement delete。

第一部分,本来是分配内存,现在已经分配好了,所以直接返回。

重载 operator new

::operator new 和::operator delete 全部可以重载,但是不推荐。类中 operator new 也可以重载,实现所需功能,这是最常用的。

class Foo{
public:
	void *operator new(size_t);
	void operator delete(void*,size_t);
	//....
};

注意,可以写出多个版本,前提是每一个版本的声明都必须有独特的参数列。(第一参数必须是size_t)只有new所调用的ctor 抛出异常,才会调用这些重载版的 operator delete()。

即使 operator delete() 未能一一对应operator new() 也不会出现任何报错。换句话说:放弃处理构造函数抛出的异常。

per-class allocator

一:

想利用类内重载operator new去接管内存的分配,然后利用内存池的观念【即创建出一大段连续空间的内存,然后将其切割成一小段一小段】,将创建的元素对象放在内存池切分好的各分段小内存片中,这样避免了多次调用new而造成生成多个带有cookie的内存空间。通过内存池的观念,可以生成一大段只带有两个头尾cookie的内存空间,而该一大段内存空间又被切分成每一小段的内存空间,且其中的每一小段内存空间片都可以共享这一整体的cookie信息。

因为为了能将一大段内存空间切分成一小段一小段,然后通过单向链表的形式串接起来,所以必须多引入一个Screen* next指针。但这又会增加class Screen的大小【增加了4字节】。

二:第一个占用了一个指针,浪费空间

这个版本通过union关键字来减少使用next而所占耗的内存!

注意:上面两个版本的operator delete操作都没有将内存空间回收还回给系统,而是仍然存在的。虽然operator delete操作没有将这些分配的内存空间释放掉,但其仍在控制中即仍可继续重新使用【只不过freeStore或headOfFreeList此时又重新跑回整个一大块内存空间的头端】,所以不算内存泄漏!

三:上面的版本不具有复用性

将分配特定尺寸区块的memory allocator包装成一个class allocator,这样每个allocator object都是个分配器,体内维护一个free lists,不同类(如下面的class Foo,class Goo等) 里面调用生成的各自allocator objects维护不同的free lists。

由上知,class Foo或class Goo其operator new或operator delete最终调用的都是allocator object所维护的free list而进行操作的!

另外,class Foo或class Goo中,应注意到:

static allocator myAlloc,即myAlloc必须是个静态成员变量,且在类外定义(赋初值)。如果其不是静态成员变量时,则在构建class Foo类对象时,是没办法调用到myAlloc的。因为非静态成员变量只能通过对象调用【但此时Foo对象还没生成又如何调用!!】。而myAlloc又是用来生成Foo类对象的,所以得通过类名调用即应设置为static类型。

而class allocator的如下:

class allocator{
private:
	struct obj{
		struct obj* next;
	};
public:
	static void* allocate(size_t);
	static void deallocate(void*, size_t);
private:
	obj* freeStore = nullptr;
	const int CHUNK = 5; // 标准库一般设置为20
};
void* allocator::allocate(size_t size){
	obj* p;
	if(!freeStore){
		// linked list为空,则申请一大块
		size_t chunk = CHUNK * size;
		freeStore = p =(obj*)malloc(chunk); // 这里直接调用malloc进行分配空间
		// 将分配的一大块切分成5小段,并串接起来
		for(int i = 0; i < (CHUNK - 1); ++i){
			p->next = (obj*)((char*)p + size);
			p = p->next;
			// 上面这两步相当于p->next = p + 1,
			// 只不过这里需要适应不同的类下的操作,因而设置成这种形式!!
		}
		p->next = nullptr; // 最后一小段的下一个位置指向空
	}
	p = freeStore;
	freeStore = freeStore->next;
	return p;
}
void allocator::deallocate(void* p, size_t){
	// 将要删除的*p的位置调整为free list的头端
	((obj*)p)->next = freeStore;
	freeStore = (obj*)p;
}

四、macro for static allocator(per-class allocator 4)

由第三版本知,其黄色部分我们想将其定义为宏操作,进一步简化代码内容:

// DECLARE_POOL_ALLOC  used in class definition
#define DECLARE_POOL_ALLOC()\
public:\
    void* operator new(size_t size){
        return myAlloc.cllocate(size);
    }\
    void operator delete(void* p){
        myAlloc.deallocate(p, 0);
    }\
protected:\
    static allocator myAlloc;

// IMPLEMENT_POOL_ALLOC   used in class implementation file
#define IMPLEMENT_POOL_ALLOC(class_name)\
    allocator class_name::myAlloc;

使用实例如图所示:

在类内进行宏声明,在类外进行宏定义【告诉编译器传入参数的class type】

New Handler

=default,=delete

一个是需要默认版本,另一个是这个函数我不要。

这两个函数不仅使用构造,同时适用于 operator new 和 operator delete。

到此这篇关于C++详细讲解内存管理工具primitives的文章就介绍到这了,更多相关C++ primitives内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++详细讲解内存管理工具primitives

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++内存管理工具primitives怎么用

本篇内容主要讲解“C++内存管理工具primitives怎么用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++内存管理工具primitives怎么用”吧!primitives分配释放属于是否
2023-07-02

C语言可变参数与内存管理超详细讲解

有时,您可能会碰到这样的情况,您希望函数带有可变数量的参数,而不是预定义数量的参数。C语言为这种情况提供了一个解决方案,这篇文章主要介绍了C语言可变参数与内存管理
2023-01-02

C++技术中的内存管理:内存管理工具和库的介绍

c++++ 内存管理:内存管理工具:调试器用于识别内存错误;内存分析工具提供内存使用情况见解。内存管理库:智能指针自动管理内存分配和释放,例如 c++11 的 unique_ptr 和 shared_ptr;boost 库提供更丰富的智能指
C++技术中的内存管理:内存管理工具和库的介绍
2024-05-08

C++中常见的内存管理问题的详细解析

C++是一种强大的编程语言,但同时也是一种需要仔细处理内存管理的语言。在使用C++编写程序时,经常会遇到内存管理问题。本文将详细解析C++中常见的内存管理问题,并提供具体的代码示例,帮助读者理解和解决这些问题。一、内存泄漏(Memory L
2023-10-22

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录