我有一个函数“管道”,可以产生最终结果和一些中间结果。我正在寻找一种方法来通过清理不再需要的中间结果来减少峰值内存。
如果我不关心中间结果的内存,这就是它的样子。 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);
}
这些是我想出的方法:
一个。使用 new
和 delete
在不再需要它们时进行清理。但是,对 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/