使用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中,内存的引用计数一直是一个让人比较头疼的问 ...
随机推荐
- 汉字转整数,比系统简单易用!a2iLxx (覆盖物 16十六进制,VC6亲测可用)请提供意见~
#include "string.h" #define INVALID_VALUE_LXX ((1 << (8 * sizeof(int) -1)) - 1) /*有符 ...
- BZOJ 1355 Baltic2009 Radio Transmission KMP算法
标题效果:给定一个字符串,求最小周期节(不能整除) 示例Hint这是错误的忽略了就好了 环路部分应该是cab 这个称号充分利用KMP在next自然阵列,那是,n-next[n]它表示一个循环节 POJ ...
- OracleServiceORCL服务不见了怎么办
用管理员身份运行命令提示符(CMD) 然后输入“oradim -new -sid orcl”即可
- TCP连接状态
TCP 连接状态按 TCP 协议的标准表示法, TCP 可具有如下几种状态,为讨论方便,如下讨论中区分服务端和客户端,实际软件处理上对二者一视同仁. CLOSED关闭状态.在两个通信端使用“三路握手” ...
- JDBC连接池的简单实现
首先解释一下,我在做自己android发育.java web这是我的弱点,就在最近,京东云免费,因此,要折腾几.有一点经验,特别是作为共享. 假设内容的文章是错,还请高手指正. 我在这里web结束,需 ...
- Introducing Visual Studio’s Emulator for Android
visual studio 2015支持Android开发了. Microsoft released Visual Studio 2015 Preview this week and with it ...
- Linux环境编程相关的文章
Linux环境编程相关的文章 好几年没有接触Linux环境下编程了,好多东西都有点生疏了.趁着现在有空打算把相关的一些技能重拾一下,顺手写一些相关的文章加深印象. 因为不是写书,也受到许多外部因素限制 ...
- HDU 1385 Minimum Transport Cost 最短路径题解
本题就是使用Floyd算法求全部路径的最短路径,并且须要保存路径,并且更进一步须要依照字典顺序输出结果. 还是有一定难度的. Floyd有一种非常巧妙的记录数据的方法,大多都是使用这种方法记录数据的. ...
- WebService使用JSON格式传递笔记+JQuery测试
原文WebService使用JSON格式传递笔记+JQuery测试 因为一些因素,必须改写WebService,很传统,但是很多公司还在用.. 因为XML 的关系,不想让他传递数据的时候过度肥大,所以 ...
- Floodlight 在 ChannelPipeline 图
我们知道,在Netty架构,一个ServerBootstrap用于生成server端的Channel的时候都须要提供一个ChannelPipelineFactory类型的參数,用于服务于建立连接的Ch ...