c++ - C++中用户定义类的动态内存分配和自动分配的区别
问题描述
我有一个类“DMRecSessionObj”,它有两个整数、一个字符串和一个向量作为其数据成员。
class DMRecSessionObj
{
private:
int callNum;
int totCalls;
std::string sessionKey;
std::vector<DMRecord>RecList;
public:
...
};
创建 DMRecSessionObj 对象后,根据需要向其中推入数据时,向量 RecList 的大小将在 150000 左右。几个这样的 DMRecSessionObj 对象将存储在静态映射中。
static std::map<string,DMRecSessionObj*> mapExpSessData;
所以,我想知道创建 DMRecSessionObj 对象的更好选择。
DMRecSessionObj* dmRec = new DMRecSessionObj(); //Dynamic memory allocation
DMRecSessionObj dmRecSessionObj; //Automatic memory allocation
问这个问题的目的是了解在这两种情况下需要注意的影响。
- 动态内存分配
- 编译器自动分配内存
考虑到高内存要求作为场景,请提出更好的选择。
提前致谢
解决方案
作为一个粗略的经验法则,如果您new
直接使用运算符,则应考虑使用标准容器(std::vector
,std::map
等)并避免使用原始指针并且不要new
直接使用运算符。
作为另一个粗略的经验法则,如果您的内存使用量很大(例如,由于大数组或大地图),那么您应该再次考虑使用可调整大小的标准容器(即可以增长以容纳更多元素或更大map) 喜欢std::vector
and std::map
,而不是std::array
(在编译时设置了大小)。
这两个经验法则的原因是可调整大小的标准容器执行动态内存分配,可以自动调整自己的大小(当您在使用它们时遵守规则时)。实际上,程序可以使用动态内存分配(它使用已知的,不准确的,称为“堆内存”)来分配更多的内存,而不是使用静态或自动内存持续时间的变量或对象(它使用已知的,不准确的,作为“堆栈内存”,其中程序可用的“堆栈内存”实际上比“堆内存”少)。
根据您的描述,如果我要使用static
地图,我会将其更改为;
static std::map<std::string,DMRecSessionObj> mapExpSessData; // note no pointer here
然后使用这样的循环使用代码填充它(理论上,它可能在循环体中)
std::string string key = obtain_string_from_somewhere();
DMRecSessionObj object = read_object_from_somewhere();
mapExpSessData[key] = object;
这允许映射处理自己的动态内存分配。这样,如果您需要管理地图的内容(例如删除条目或添加条目),您可以使用std::map
为此目的提供的操作。如果您正确使用这些操作,通常会正确清理内存(例如new
,当您从地图中删除条目时,不会因为忘记释放使用 operator 手动创建的对象而导致泄漏)。
上面的对象key
和object
上面的对象是自动创建的,这意味着当它们所在的范围完成时它们将不复存在。从技术上讲,这可能(不一定会)导致在您填充地图时出现额外的对象)。如果地图很大,我建议额外的对象是微不足道的。
请注意,作为一般规则,需要收集 150000 个对象(甚至是小对象)的程序通常可以合理化。如果一个程序在地图(或任何容器)中有 150000 个对象,那么实际上,通常会证明程序实际使用了其中的一小部分。因此,最好做一些设计工作来预测或估计内存中实际需要哪些对象,从而实现更小的映射或向量。这可能需要权衡取舍,例如需要从存储中读取不经常使用的对象,而不是始终将它们保存在映射中 - 但可以显着减少程序的内存使用量。这可以在相当多的设置中显着提高性能 - 例如您的程序在资源有限的机器上运行的位置,
请记住,使用static
变量也会带来严重的惩罚。如果您进行搜索,您会发现很多解释为什么static
最好避免使用变量,以及替代方案是什么。
推荐阅读
- jasmine - 模拟方法返回未定义
- reactjs - React - 尽管程序运行良好,但 useMemo 发出警告。(useMemo 有一个不必要的依赖)
- javascript - 如何在反应js中将此文本区域输入转换为此示例
- laravel - 使用 Laravel 复制一列
- java - Android:使用从 URI 路径检索的文件返回 FileNotFound 异常?
- php - Laravel 为响应内容添加 php 通知
- excel - 使用 Google 表格公式进行正则表达式替换和拆分
- postgresql - 如何在谷歌云计算虚拟机上调试 postgres 连接问题
- firefox - 安全连接失败:无法显示您尝试查看的页面,因为无法验证接收数据的真实性
- c++ - 为什么我的 camelcase 函数不适用于大字符串?