使用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中,内存的引用计数一直是一个让人比较头疼的问 ...
随机推荐
- HTML5多图片拖拽上传带进度条
前言 昨天利用css2的clip属性实现了网页进度条觉得还不错,但是很多情况下,我们在那些时候用进度条呢,一般网页加载的时候如果有需要可以用,那么问题就来了,怎么才算整个加载完毕呢,是页面主要模块加载 ...
- 【百度地图API】暑假放假回老家——城市切换功能
原文:[百度地图API]暑假放假回老家--城市切换功能 任务描述: 酸奶小妹放寒假啦,要从北京呼啦一下飞回重庆呢.现在百度地图API上不能直接切换城市,怎么办呢? 如何实现: 利用API先搜索到要去城 ...
- C--运算符,表达式和语句实例
//第五章 运算符,表达式和语句 #include<stdio.h> //引入头文件 #include<math.h> #define ADJUST 7.64 //定义常量 # ...
- 记录近期小改K-Means至MapReduce上的心得
背景: 在所有聚类算法中KMeans算是表面上最简单的一种,没有过多恼人的古希腊符号公式,没有过分繁杂的公式嵌套.对于一个初学矩阵或者仅有向量概念的非专业人士的来说,不可不畏是一把踹门利器.这个世界上 ...
- centos 7安装mysql5.5
首先centos7 已经不支持mysql,因为收费了你懂得,所以内部集成了mariadb,而安装mysql的话会和mariadb的文件冲突,所以需要先卸载掉mariadb,以下为卸载mariadb,安 ...
- 【solr这四个主题】在Tomcat 部署Solr4.x
1.安装Tomcat (1)下载并解压缩到/opt/tomcat在 # cd /opt/jediael # tar -zxvf apache-tomcat-7.0.54.tar.gz # mv apa ...
- Ios 从无到有项目 MVVM模式(两)
1.该项目昨天,我认为未来,有三个部分,第一部分是基于一个在线数据查询对聚合,第二部分是xmpp聊天功能,第三部分是很多其他功能. 2.在线咨询,使用的主要技术,它是get要求或post要求,该网上查 ...
- jQuery EasyUI API - Grid - DataGrid [原创汉化官方API]
最近在学习jQuery EasyUI,发现中文的文档好少,部分文档不错但它是鸟语的,为了大家也为了自己学习吧,汉化做一下笔记. 有没有说清楚的,或者翻译不正确的地方还请大家谅解指出.. 由于工作时间原 ...
- Spring之IOC容器加载初始化的方式
引言 我们知道IOC容器时Spring的核心,可是如果我们要依赖IOC容器对我们的Bean进行管理,那么我们就需要告诉IOC容易他需要管理哪些Bean而且这些Bean有什么要求,这些工作就是通过通过配 ...
- js面向对象学习总结
1.函数作为参数进行传递 function a(str,fun){ console.log(fun(str)) }; function up(str){ return str.toUpperCase( ...