传递堆栈对象的所有权而不重复

问题描述 投票:0回答:2

第三方库具有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的正确选择。我如何:

  1. computeHuge()构造函数中调用Foo
  2. Bar保留h的所有权
  3. 全部是否需要内存中有h的两个副本?
c++ memory-management shared-memory
2个回答
1
投票

如果Huge是可移动的,则不会进行任何复制:

class Bar {
  Huge h;
  Bar(Huge huge): h(std::move(huge)) {}   // move huge into its final place, h
};

class Foo {
  Bar b;

  Foo() {
    Huge h = computeHuge();
    b = Bar(std::move(h));   // move h into constructor argument
    // h cannot be used here anymore
  }
};

出于调试目的,这是一个(小)Huge,不能复制,只能移动。每次尝试复制都是编译器错误:

struct Huge {
    Huge() = default;
    Huge(Huge&& other) { std::cout << "move "; }
    Huge(const Huge& other) = delete;
    Huge& operator=(Huge&& other) { std::cout << "move= "; return *this; }
    Huge& operator=(const Huge& other) = delete;
};

0
投票

这可能可行:在Bar中创建一个空对象,在Bar中添加一个函数以获取对其h的引用。

#include <iostream>

#include <vector>

class Huge
{
public:
    std::vector<int> v;
};

class Bar
{
public:
    Bar() : h() {};
    Huge& GetHuge() { return h; };

    Huge h;
};

class Foo
{
public:
    Foo() : b()
    {
        Huge& h = b.GetHuge();

        // computeHuge();
        h.v.push_back(25);
    };

    int GetHugeOneInt(int ix)   
    {
        Huge& h = b.GetHuge();
        int i = h.v[ix];
        return i;
    };

    Bar b;
};


int main()
{
    Foo* myfoo = new Foo();
    int i = myfoo->GetHugeOneInt(0);
    std::cout << "Hello World!\n" << i; 

    std::getchar();
}
© www.soinside.com 2019 - 2024. All rights reserved.