在std容器上执行一系列操作时最大限度地减少峰值内存使用量

时间:2015-08-29 20:54:11

标签: 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);
}

℃。使用块。

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);
}

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

2 个答案:

答案 0 :(得分:1)

老实说,我会选择D,因为你的某些变量之间存在某种联系,将这些代码提取到函数中不仅可以解决你的内存问题,而且还可以使用代码本身更好地记录你的意图(我相信你可以在你的代码中提出好的不言自明的名字)。如果你对函数签名使用更好的方法,那么唯一的问题当然是性能(假设你不控制 { "categoryName": "Appetizers & Sides", "categories": [ { "categoryID": "294", "parentID": "304", "subjectID": "7", "categoryName": "Apps and Side Dishes (Laura)", "categoryDescription": "Learn to make amazing appetizers and side dishes with Laura in the Kitchen.", "videosCount": "101", "forumCategoryID": "163" }, { "categoryID": "285", "parentID": "304", "subjectID": "7", "categoryName": "Side Dishes", "categoryDescription": "Side dish recipes for salads, vegetables, sauces with Hilah cooking.", "videosCount": "38", "forumCategoryID": "163" } ] } 函数:即。

compute

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

答案 1 :(得分:-2)

如果您要存储指向这些容器中对象的指针,那么删除它们(或者只是让它们超出范围)不会释放对象正在使用的内存,只会释放容器的内存本身。您也必须删除容器中的每个对象。

否则,是的,在STD容器上使用new和delete非常有意义。它还意味着在堆上而不是堆栈上为它们分配内存,这可能是明智的,因为堆栈有利于快速分配,如果你对它进行过多的转储就会耗尽。您可能还会遇到分页问题。

要真正解决您的问题,这将有助于更多地了解您正在做的事情。你真的需要使用STD容器吗?你可以使用数组吗?容器中的对象是否对每个容器都是唯一的,或者它们是否被重新排列到不同容器中的同一堆对象?有没有办法将操作分解为较小的数据集而不是像这样的一系列容器运行?