(C ++)寻找减少内存使用量的技巧

时间:2010-10-08 16:08:42

标签: c++ memory-management

我遇到了一个严重且严格的内存限制问题。我是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。

7 个答案:

答案 0 :(得分:21)

我猜你的问题的潜台词是你的大部分内存使用是数据,而不是代码。以下是一些提示:

  • 如果您的数据范围有限,请充分利用它。如果整数的范围是-128到127,则使用char而不是int,或unsigned char,如果它是0到255.同样使用int16_tuint16_t作为范围-32768..32767和0..65535。
  • 重新排列结构元素,使较大的项目首先出现,这样数据对齐不会在结构的中间留下死区。您通常也可以通过编译器选项控制填充,但最好只是首先使布局最佳。
  • 使用不会产生大量开销的容器。例如,使用vector代替list。使用boost::ptr_vector代替包含std::vector的{​​{1}}。
  • 避免虚拟方法。添加到结构或类的第一个虚方法会向vtable添加一个隐藏指针。

答案 1 :(得分:9)

不,常规成员函数不会使类或结构更大。引入虚拟函数可能(在许多平台上)向类添加vtable指针。在x86上会增加四个字节的大小。但是,添加虚函数时不再需要内存 - 一个指针就足够了。类或结构类型的大小永远不为零(无论它是否具有任何成员变量或虚函数)。这是为了确保每个实例占用自己的内存空间(source,第9.0.3节)。

答案 2 :(得分:5)

在我看来,减少内存的最佳方法是考虑算法空间的复杂性,而不仅仅是做好的代码优化。重新考虑诸如动态编程表,不必要的副本之类的东西,通常是任何在内存效率方面都有疑问的东西。此外,尝试在不再需要时尽早释放内存资源。

答案 3 :(得分:1)

对于你的最后一个例子(树),你可以使用带有XOR的聪明的hack用单个节点指针替换两个节点指针,如here所述。这仅适用于以正确顺序遍历树的情况。显然这会损害代码的可读性,因此应该是最后的手段。

答案 4 :(得分:0)

您可以使用编译标志进行一些优化。如果您使用的是g ++,可以使用以下命令进行测试: -O2

关于这个主题有很多主题:

C++ Optimization Techniques

Should we still be optimizing "in the small"?

Constants and compiler optimization in C++

What are the known C/C++ optimizations for GCC

答案 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总是有一个接近完整的二叉树,所以标准实现使用一个隐式树,它根本不需要任何指针。

最重要的是,找到一个不同的算法可能会完全改变游戏......