c++ - 在标准容器上执行一系列操作时最小化峰值内存使用

标签 c++ memory temporary-objects

我有一个函数“管道”,可以产生最终结果和一些中间结果。我正在寻找一种方法来通过清理不再需要的中间结果来减少峰值内存。

如果我不关心中间结果的内存,这就是它的样子。 B、C、D、E 和 F 都是 std 容器,每个容器都有超过一百万个对象。

void A::getF(F &f) {
  B b;
  C c;
  computeBAndC(b, c);
  D d;
  computeD(b, c, d);
  // b and c no longer needed
  E e;
  computeE(d, e);
  // d no longer needed
  computeF(e, f);
}

这些是我想出的方法:

一个。使用 newdelete 在不再需要它们时进行清理。但是,对 std 容器使用 new 和 delete 有意义吗?

void A::getF(F &f) {
  B *b = new B;
  C *c = new C;
  computeBAndC(b, c);
  D *d = new D;
  computeD(b, c, d);
  // b and c no longer needed
  delete b;
  delete c;
  E e;
  computeE(d, e);
  // d no longer needed
  delete d;
  computeF(e, f);
}

B.使用 std 容器的 swap 函数在使用后清除它们的内存。

void A::getF(F &f) {
  B b;
  C c;
  computeBAndC(b, c);
  D d;
  computeD(b, c, d);
  // b and c no longer needed
  B().swap(b);
  C().swap(c);
  E e;
  computeE(d, e);
  // d no longer needed
  D().swap(d);
  computeF(e, f);
}

C.使用积木。

void A::computeF(F &f) {
  E e;
  {
    D d;
    {
      B b;
      C c;
      computeBAndC(b, c);
      computeD(b, c, d);
      // b and c no longer needed
    }
    computeE(d, e);
    // d no longer needed
  }
  computeF(e, f);
}

D.重构以便在函数范围末尾删除中间结果:

void A::getF(F &f) {
  E e;
  getE(e);
  computeF(e, f);
}

void A::getE(E &e) {
  D d;
  getD(d);
  computeE(d, e);
}

void A::getD(D &d) {
  B b;
  C c;
  computeBAndC(b, c);
  computeD(b, c, d);
}

这些方法的优缺点是什么?这些真的会减少峰值内存使用吗?有没有更好的办法?

最佳答案

老实说,我会选择选项 D,因为考虑到您的一些变量之间存在某种联系,将此代码提取到函数中不仅可以解决您的内存问题,而且还可以更好地使用您的代码本身记录您的意图(我相信你可以在你的代码中想出很好的不言自明的名字)。唯一的问题当然是性能,如果你对函数签名使用更好的方法(假设你不控制 compute 函数:即

E A::computeE(const D& d) {
    E e;
    computeE(d, e);
    return E;
}

我从您的评论中了解到您只能使用没有移动语义的 C++98。但是,编译器长期以来一直能够执行命名的返回值优化 - 在你的情况下,我会尝试测试你的编译器使用 NRVO (和复制省略)的能力,如果它很好 - 使用更自然的(IMO ) 我概述的签名 - 否则我会使用你的选项 D。

关于c++ - 在标准容器上执行一系列操作时最小化峰值内存使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32290576/

相关文章:

c++ - 将成员函数指针传递给父类

c++ - 两个临时对象的地址在同一个表达式中是否保证不同?

c - 内存:在图表的顶部或底部的高地址?

c++ - 临时延长生命周期

c++ - 通过获取对子对象的引用来延长临时对象的生命周期

c++向日期添加或减去值

c++ - 编译错误 g++

c++ - 我可以避免返回函数的模板返回类型吗?

c - 如何将变量设置为与另一个指针分配和指向的空间量相同?

memory - 如何知道 ffmpeg 中一个 AVPacket 的大小?