C++ (C+;+;)寻找减少内存使用的技巧
我有一个非常严格的内存限制问题。我是一个CPP极客,我想减少我的内存使用。请给我一些提示C++ (C+;+;)寻找减少内存使用的技巧,c++,memory-management,C++,Memory Management,我有一个非常严格的内存限制问题。我是一个CPP极客,我想减少我的内存使用。请给我一些提示 我的一个朋友建议从结构中取出函数。 例如,不使用: struct node{ int f() {} } 他建议我使用: int f(node x) {} 这真的有用吗 注意:我有很多我的结构副本 以下是更多信息: 我正在为一个在线评委的练习题编写一个片段树。我在结构中得到树节点。my struct具有以下变量: int start; int end; bool flag;
我的一个朋友建议从结构中取出函数。 例如,不使用:
struct node{
int f()
{}
}
他建议我使用:
int f(node x)
{}
这真的有用吗
注意:我有很多我的结构副本
以下是更多信息: 我正在为一个在线评委的练习题编写一个片段树。我在结构中得到树节点。my struct具有以下变量:
int start;
int end;
bool flag;
node* left;
node* right;
内存限制为16 MB,我使用的是16.38 MB。不,常规成员函数不会使类或结构变大。引入虚拟函数可能(在许多平台上)会添加指向该类的指针。在x86上,这会将大小增加四个字节。不过,添加虚拟函数时不需要更多内存——一个指针就足够了。类或结构类型的大小从不为零(无论它是否有任何成员变量或虚拟函数)。这是为了确保每个实例都占用自己的内存空间(,第9.0.3节)。您可以使用编译标志进行一些优化。如果您使用的是g++,则可以使用:-O2进行测试 关于这个主题,有很多好的线索:
,在我看来,减少内存的最好方法是考虑算法空间的兼容性,而不是做精细的代码优化。重新考虑动态编程表、不必要的副本,通常是内存效率方面有问题的任何东西。另外,只要不再需要内存资源,就尽量尽早释放它们。根据你问题的潜台词,我猜大部分内存使用是数据,而不是代码。以下是一些提示:
- 如果您的数据范围有限,请充分利用它。如果整数的范围是-128到127,则使用
而不是int,如果是0到255,则使用char
。同样,对于-32768..32767和0..65535的范围,使用unsigned char
或int16\u t
uint16\u t
- 重新排列结构元素,因此较大的项首先出现,这样数据对齐不会在结构中间留下死区。您通常也可以通过编译器选项来控制填充,但最好首先使布局优化
- 使用开销不大的容器。例如,使用
代替向量
。使用而不是列表
包含std::vector
shared\u ptr
- 避免虚拟方法。添加到结构或类的第一个虚拟方法将向vtable添加隐藏指针
- 在第一个函数中,
是f()
节点的成员函数
- 在第二个函数中,
是一个自由函数(或命名空间作用域)。(还要注意,两个f()
的签名是不同的。)f()
f()
是一个inline
成员函数。在类主体内定义成员函数使其内联。虽然内联没有得到保证,但它只是对编译器的一个提示。对于具有小实体的函数,最好将它们内联,因为这样可以避免过度调用函数。然而,我从来没有看到这是一个成功或失败的因素
如果您不希望或f()
不适合内联,则应在类主体之外(可能在.cpp文件中)将其定义为:
如果代码中存在内存使用问题,那么上述主题很可能不相关。探索以下内容可能会给您一些提示
- 查找程序中所有类的大小。使用
查找此信息,例如sizeof(节点)sizeof
- 查找程序正在创建的每个类的最大对象数
- 使用上述两系列信息,估计程序在最坏情况下的内存使用情况 最坏情况下的内存使用率=n1*sizeof(node1)+n2*sizeof(node2)+
- 减少类的最大实例数。这可能是不可能的,因为这取决于程序的输入,而这超出了您的控制范围
- 减少每个类的大小。不过这是在你的控制之下
如何减少班级规模?尝试将类成员紧凑地打包以避免出现错误。正如其他人所说,拥有方法不会增加结构的大小,除非其中一个是虚拟的 您可以使用位字段有效地压缩数据(这对于布尔值…)尤其有效。此外,您可以使用索引而不是指针来保存一些字节 请记住,要将节点分配成大块,而不是单独分配(例如,使用new[]一次,而不是常规的new多次),以避免内存管理开销 如果不需要节点指针提供的全部灵活性,可以减少或消除它们。例如,heapsort总是有一个接近完整的二叉树,因此标准实现使用隐式树,它根本不需要任何指针
最重要的是,找到一个不同的算法可能会完全改变游戏…对于最后一个示例(树),您可以使用一个巧妙的XOR hack,将两个节点指针替换为一个节点指针,如前所述。但是,这仅在以正确的顺序遍历树时有效。显然,这会损害代码的可读性,因此应该是最后的手段。您的程序是做什么的?它使用什么算法?很难笼统地谈论优化。如果您在linux上,那么您可以使用valgrind/massif来查看您的h
int node::f() { /* stuff here */ }