首页 > 解决方案 > 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

问这个问题的目的是了解在这两种情况下需要注意的影响。

  1. 动态内存分配
  2. 编译器自动分配内存

考虑到高内存要求作为场景,请提出更好的选择。

提前致谢

标签: c++memory-management

解决方案


作为一个粗略的经验法则,如果您new直接使用运算符,则应考虑使用标准容器(std::vector,std::map等)并避免使用原始指针并且不要new直接使用运算符。

作为另一个粗略的经验法则,如果您的内存使用量很大(例如,由于大数组或大地图),那么您应该再次考虑使用可调整大小的标准容器(即可以增长以容纳更多元素或更大map) 喜欢std::vectorand 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 手动创建的对象而导致泄漏)。

上面的对象keyobject上面的对象是自动创建的,这意味着当它们所在的范围完成时它们将不复存在。从技术上讲,这可能(不一定会)导致在您填充地图时出现额外的对象)。如果地图很大,我建议额外的对象是微不足道的。

请注意,作为一般规则,需要收集 150000 个对象(甚至是小对象)的程序通常可以合理化。如果一个程序在地图(或任何容器)中有 150000 个对象,那么实际上,通常会证明程序实际使用了其中的一小部分。因此,最好做一些设计工作来预测或估计内存中实际需要哪些对象,从而实现更小的映射或向量。这可能需要权衡取舍,例如需要从存储中读取不经常使用的对象,而不是始终将它们保存在映射中 - 但可以显着减少程序的内存使用量。这可以在相当多的设置中显着提高性能 - 例如您的程序在资源有限的机器上运行的位置,

请记住,使用static变量也会带来严重的惩罚。如果您进行搜索,您会发现很多解释为什么static最好避免使用变量,以及替代方案是什么。


推荐阅读