使用C++做算法时,对内存的管理的办法
使用C++做算法时,对内存的管理的办法
最近老是在想C++的内存控制机制,查了一些资料所以有点想法,自己记录一下免得以后自己忘了。
1. 需求
在做线性代数的算法时,首要的就实现Matrix这个类。由于Matrix的行列可变化,所以必须使用动态的内存分配。动态的内存分配就必须要考虑内存的申请和释放,以及动态内存在不同对象之间的传递机制。考虑到算法的复杂性,所以在Matrix之外不打算使用指针,以降低算法实现的复杂度。
2. 可实现的方法
总体上,我能找到的方法有以下2种。
- 利用默认的构造复制构造函数和默认重载以及赋值操作函数动态申请和释放内存和引用计数机制实现不同对象之间对同一块内存的共享,最后只有一个对象负责将动态申请的内存块释放掉,例如OpenCV中的Mat等类使用的就是这种技术。
- 利用C++的复制构造函数和重载赋值操作,将对象的复制构造和赋值统统进行深度复制,这样每个对象负责一个动态申请的内存块,互不干扰。例如STL的vector等容器。
感谢C++11引入的分享指针和右值引用,所以还有两种新的办法。
3. 使用分享指针。分享指针将负责动态申请的内存的释放,利用C++的默认复制构造函数和默认重载赋值操作即可。由于分享指针不能动态申请内存块,所以 以动态申请vector<T>代替。该方法与上述方法1相似,只是利用分享指针控制内存。
4. 利用C++的右值引用,实现移动语义。重载C++类的复制构造函数和重载赋值操作,实现对动态数据的深度复制,利用移动构造函数和移动赋值操作实现对 动态数据的管理权的获取。
3. 方法的比较
- 第一种方法算是一种使用比较流行的办法。好处自然就不必说了,不同对象之间可以共享动态内存,在数据量大的时候避免重复移动数据造成开销,程序的效率高。但是,其优点也是其缺点,在数学计算和赋值中,必须时刻警惕,到底哪些对象共享了内存,或者现在对象的内存是谁申请的等问题,反而让算法编写充满了紧张气氛。为了安心,还得显示的实现深度赋值操作,在数据之间赋值时显示的调用,让程序看起来不那么的美观。
- 第二种方法是一种很安全,也是C++03中提倡的方法。该方法将动态申请的数据进行深度复制,每个对象一份,互不干扰,跟操作基本数据类型一样。当然,在函数调用中可以采用左值引用方法,同样也具备效率优势。但是,在一些临时数据出现的地方,这种方法就需要进行没必要的深度复制,浪费计算资源,例如函数返回临时对象。同样,如果数据量大,该方法将大量的使用堆中数据,这时,不得不使用指针来缓解,而这又增加了算法编程的复杂度。
- 第三种方法与第一种方法类似,只是实现方法不一样,不再赘述。
- 第四种方法是C++11提倡的方法,总体来说,实在第二种方法基础之上增加了移动语义,将利用临时变量的地方可以实现动态数据管理权的转让,这样不必进行深度的数据复制,提高程序的运行效率。该方法需要理解新引入的右值引用(以前的引用称为左值引用),编译器遇到右值将调用移动构造函数或者移动赋值操作。同样,也可以强制语义移动,如果非得进行移动的话,例如临时对象作为返回值。该方法基本上缓解了动态内存管理和数据安全效率之间的矛盾。但是,对象之间的数据是不分享的,如果想让对象之间分享数据,该方法不支持。
4. 总结
如果是用于线性代数计算,而且不适用指针的话,我会采用第四种方法和引用来编写算法。只是,目前支持C++11的编译器不多,如Visual 2012和Gnu g++4.8,因此,写出来的程序只能使用原来的代码用在较新的编译器里,而不能使用在不支持C++11编译器里。
使用C++做算法时,对内存的管理的办法的更多相关文章
- MS SQL SERVER执行大脚本文件时,提示“内存不足”的解决办法
问题描述: 当客户服务器不允许直接备份时,往往通过导出数据库脚本的方式来部署-还原数据库, 但是当数据库导出脚本很大,用Microsoft SQL Server Management Studio执行 ...
- 初学vue 在做项目时遇到的问题与解决办法(使用element组件)(二)
表格每行里都有按钮 <el-table-column prop="option" label="操作" align="center" ...
- 亿级数据时,内存性能低于IO性能
最近因项目需要,需要生成有0到99999999共1亿的不重复数,于是想着直接将这些数据生成为一个文件就可以了,代码如. private void generate(string savePath) { ...
- 复习做UWP时涉及到的几种加密签名相关
本人菜鸟一枚,大学里凭兴趣学了一点WP的皮毛,后来又幸运(或者不幸)的进了一家专注于Windows生态的公司做了一段时间的UWP.在博客园写点自己遇到的东西,作为分享,也作为自己的备忘,如果有错误的地 ...
- 关于Class对象、类加载机制、虚拟机运行时的内存布局的全面解析和推测
简介: 本文是对Java的类加载机制,Class对象,反射原理等相关概念的理解.验证和Java虚拟机中内存布局的一些推测.本文重点讲述了如何理解Class对象以及Class对象的作用. 欢迎探讨,如有 ...
- Java运行时环境---内存划分
背景:听说Java运行时环境的内存划分是挺进BAT的必经之路. 内存划分: Java程序内存的划分是交由JVM执行的,而不像C语言那样需要程序员自己买单(C语言需要程序员为每一个new操作去配对del ...
- [二]Java虚拟机 jvm内存结构 运行时数据内存 class文件与jvm内存结构的映射 jvm数据类型 虚拟机栈 方法区 堆 含义
前言简介 class文件是源代码经过编译后的一种平台中立的格式 里面包含了虚拟机运行所需要的所有信息,相当于 JVM的机器语言 JVM全称是Java Virtual Machine ,既然是虚拟机, ...
- 了解JVM运行时的内存分配
了解JVM运行时的内存分配 前言 上文中,在介绍运行时数据区域中的 JAVA 堆时,提到了 JVM 中的堆,一般分为三大部分:新生代.老年代.永久代,本文将进一步了解运行时的内存分配情况. 正文 1. ...
- objective-c启用ARC时的内存管理 (循环引用)
PDF版下载:http://download.csdn.net/detail/cuibo1123/7443125 在Objective-C中,内存的引用计数一直是一个让人比较头疼的问 ...
随机推荐
- Swift学习笔记(一)搭配环境以及代码运行成功
原文:Swift学习笔记(一)搭配环境以及代码运行成功 1.Swift是啥? 百度去!度娘告诉你它是苹果最新推出的编程语言,比c,c++,objc要高效简单.能够开发ios,mac相关的app哦!是苹 ...
- c/cpp中怎样切割字符串,相似于split的功能
在python中,假设要求当前时间的unix时间戳,我特别喜欢这么用: import time timestr = time.time() timestamp = int(timestr.split( ...
- 在线预览Excel
遇到的问题各种多 <system.web> <identity impersonate="true" userName="Administ ...
- WebForm MapPageRoute 路由配置
WebForm MapPageRoute 路由配置 MapPageRoute 应该是 ASP.NET 4.0 中的东西,但现在我是第一次使用它,使用场景是:MVC 混合使用 WebForm,然后对 ...
- Codeforces 484B Maximum Value(高效+二分)
题目链接:Codeforces 484B Maximum Value 题目大意:给定一个序列,找到连个数ai和aj,ai%aj尽量大,而且ai≥aj 解题思路:类似于素数筛选法的方式,每次枚举aj,然 ...
- Monkey源码分析之事件源
上一篇文章<Monkey源码分析之运行流程>给出了monkey运行的整个流程,让我们有一个概貌,那么往后的文章我们会尝试进一步的阐述相关的一些知识点. 这里先把整个monkey类的结构图给 ...
- hibernate实体类型映射文件
1.通过写hibernate映射文件.实体类型转换为数据库中的表 据实体类型而写的. 实体类型User.java package cn.wwh.www.hibernate.dd.property; i ...
- 为mongodb加上权限
我们知道mysql在安装的时候需要我们设置一个数据库默认的用户名和密码,mongodb也不例外,不过mongodb是默认的没有设置访问限制的,不需要输入用户名和密码都可以访问的,但是这样会十分的不安全 ...
- JavaScript中JSON字符串和JSON对象相互转化
JSON字符串转化为JSON对象的2种方式 一.使用函数eval var personsstr = '[{"Name":"zhangsan","Age ...
- 【转】怎么导出jar包
如何导出jar包 右键工程->Export->Java->JAR file->Next-> Next 选中工程和工程中你要打包的内容,如果是Android的项目,需要把M ...