我遇到了一个严重且严格的内存限制问题。我是CPP的极客,我想减少我的内存使用量。请给我一些提示。
我的一位朋友建议在我的结构中使用函数。 例如,而不是使用:
struct node{
int f()
{}
}
他建议我使用:
int f(node x)
{}
这真的有帮助吗?
注意:我的结构有很多副本。
这里有更多信息:
我正在编写某种分段树来解决在线裁判的练习问题。我在结构中获得树节点。我的struct有这些变量:
int start;
int end;
bool flag;
node* left;
node* right;
内存限制为16 MB,而我使用的是16.38 MB。
答案 0 :(得分:21)
我猜你的问题的潜台词是你的大部分内存使用是数据,而不是代码。以下是一些提示:
char
而不是int,或unsigned char
,如果它是0到255.同样使用int16_t
或uint16_t
作为范围-32768..32767和0..65535。vector
代替list
。使用boost::ptr_vector
代替包含std::vector
的{{1}}。答案 1 :(得分:9)
不,常规成员函数不会使类或结构更大。引入虚拟函数可能(在许多平台上)向类添加vtable指针。在x86上会增加四个字节的大小。但是,添加虚函数时不再需要内存 - 一个指针就足够了。类或结构类型的大小永远不为零(无论它是否具有任何成员变量或虚函数)。这是为了确保每个实例占用自己的内存空间(source,第9.0.3节)。
答案 2 :(得分:5)
在我看来,减少内存的最佳方法是考虑算法空间的复杂性,而不仅仅是做好的代码优化。重新考虑诸如动态编程表,不必要的副本之类的东西,通常是任何在内存效率方面都有疑问的东西。此外,尝试在不再需要时尽早释放内存资源。
答案 3 :(得分:1)
对于你的最后一个例子(树),你可以使用带有XOR的聪明的hack用单个节点指针替换两个节点指针,如here所述。这仅适用于以正确顺序遍历树的情况。显然这会损害代码的可读性,因此应该是最后的手段。
答案 4 :(得分:0)
您可以使用编译标志进行一些优化。如果您使用的是g ++,可以使用以下命令进行测试: -O2
关于这个主题有很多主题:
Should we still be optimizing "in the small"?
答案 5 :(得分:0)
这两种可能性并不完全相同:
f()
是node
的成员函数。f()
是一个免费(或名称空间范围)函数。 (另请注意,两个f()
的签名是不同的。)现在请注意,在第一种样式中,f()
是inline
成员函数。在类体内定义成员函数使其成为内联。尽管内联不是保证,但它只是对编译器的暗示。对于具有小体的函数,最好将它们内联,因为它可以避免函数调用。但是,我从未见过这是一个成败的因素。
如果你不想或如果f()
没有内联资格,你应该在类体(可能在.cpp文件中)之外定义它:
int node::f() { /* stuff here */ }
如果代码中存在内存使用问题,则很可能上述主题不相关。探索以下内容可能会给你一些提示
sizeof
查找此信息,例如sizeof(node)使用以上两个系列的信息,估算程序的最坏情况内存使用情况
最坏情况内存使用量= n1 * sizeof(node1)+ n2 * sizeof(node2)+ ...
如果上述数字太高,则您有以下选择:
如何减少课程的大小?请尝试紧凑地打包班级成员以避免packing。
答案 6 :(得分:0)
正如其他人所说,拥有方法不会增加结构的大小,除非其中一个是虚拟的。
您可以使用位域来有效地压缩数据(这对您的布尔值尤其有用......)。此外,您可以使用索引而不是指针来节省一些字节。
请记住以大块而不是单独分配节点(例如,使用new []一次,而不是常规新的多次)以避免内存管理开销。
如果您不需要节点指针提供的完全灵活性,您可以减少或消除它们。例如,heapsort总是有一个接近完整的二叉树,所以标准实现使用一个隐式树,它根本不需要任何指针。
最重要的是,找到一个不同的算法可能会完全改变游戏......