【发布时间】:2020-02-27 21:43:45
【问题描述】:
第三方库具有 API Huge computeHuge()。它返回对象本身,而不是引用/指针。我无法控制对象或 API。
我有两个课程:
class Bar {
Huge h;
Bar(Huge &huge): h(huge);
}
class Foo {
Bar b;
Foo() {
Huge h = computeHuge();
b = Bar(h);
}
不幸的是,这种设计(暂时)导致了一个巨大对象的两个副本:一个副本存在于Foo 构造函数中,另一个存在于Bar 对象中。一旦Foo 构造函数退出,只有一个副本,但我需要构造函数内的内存加倍。由于h 可能有数百 GB,这很重要。
解决这个问题的一个方法是让Foo成为h的所有者:
class Bar {
Huge &h;
Bar(Huge &huge): h(huge);
}
class Foo {
Bar b;
Huge h;
Foo() {
h = computeHuge();
b = Bar(h);
}
这确实成功地消除了h 的两个副本,但在我的应用程序中并没有真正意义:Bar 是持有h 的正确事物。
我该怎么做:
- 在
Foo构造函数中调用computeHuge() - 让
Bar保留h的所有权 - 所有没有在内存中需要
h的两个副本?
【问题讨论】:
-
我不相信堆栈上可以有数百 GB。通常,默认堆栈大小为 1 MB。我认为
h内部数据是动态分配的(假设您有足够大的 RAM 内存来存储数百 GB,我对此表示严重怀疑)。但是,如果您可以访问Huge的内部数据,您或许可以持有指向它的指针。 -
是的。
Huge是一个非常大的向量的包装器,这个向量大概是在堆上分配的。但我无法控制它,因为Foo()中的Huge对象将在构造函数退出时被清理,这将删除向量。即使我可以访问内部向量,我也无法阻止它在构造函数退出时被删除。我正在使用一个 非常 大的 EC2 实例,所以有足够的内存 :) -
根据给定答案中的建议,您可以移动您的
std::vector(如果您不能直接移动Huge,这是首选)。它应该可以解决问题:) -
^ 如果不是这样:让 Bar 生成(空)Huge 对象,然后在 Bar 中有一个 get-huge-reference 函数,然后用它来填充 Foo 中的对象?像图像库中的 get-image-buffer 类型函数?
-
@DaveS 你能把它写下来作为答案吗?
标签: c++ memory-management shared-memory