1

我有一个类包含我希望经常使用的数据,所以我认为最好返回一个对它的 const 引用。但是,给定一些参数,我可能需要动态创建新数据。我已经看到您可以将临时返回到常量引用,如下所示:

class Foo {
  public:
    Foo() { ... }                    //Initialize data

    LARGE_DATA getData(bool param1, bool param2) {
      if (...) {                     // For some crazy function of the parameters
        LARGE_DATA newData = ...;    // Create new data and return it
        return newData
      }
      return data;                   // Usually, will just use the default value
    }
  private:
    LARGE_DATA data;
};

void bar() {
  Foo f;
  const LARGE_DATA& data = f.getData();
  ...                                // Process data (read-only)
}

但这似乎会复制data. 我想做这样的事情:

class Foo {
  public:
    Foo() { ... }                    //Initialize data

    const LARGE_DATA& getData(bool param1, bool param2) {
      if (...) {                     // For some crazy function of the parameters
        LARGE_DATA newData = ...;    // Create new data and return it
        return newData
      }
      return data;                   // Usually, will just use the default value
    }
  private:
    LARGE_DATA data;
};

void bar() {
  Foo f;
  const LARGE_DATA& data = f.getData();
  ...                                // Process data (read-only)
}

这样可以避免不必要的副本。Visual Studio 不会抱怨这一点,但 g++ 会抱怨(而且可能是正确的)。这样做的正确方法是什么?

4

3 回答 3

1

我想我理解你的困境。在您的第一个实现中,您依赖于此处newData描述的 C++ 的一个特性,当调用函数将对其的 const 引用保存在堆栈上时,从函数返回的临时(在这种情况下)的生命周期会延长。但是如果data返回而不是newData,它将创建一个副本,然后将副本作为临时返回,这是您不想要的。

您的第二个实现试图通过返回引用来防止复制data,但这与 g++ 中断,因为newData. 您不再返回一个名为 的临时对象newData,而是返回对它的引用,根据 g++,它不符合生命周期延长的条件。

我看到了两种方法。您可以getData()分成两种方法,一种data通过返回引用返回,另一种newData通过值返回,因此创建了一个临时值。或者您可以保存newData为该类的数据成员,返回对该类的引用data,并在每次需要重新计算时将其覆盖,但仅当您只需要读取newData之间的给定值时才有效连续调用getData().

于 2013-02-26T09:03:22.227 回答
0

您可能应该通过在返回对它的引用之前存储newData某处来保留所有权Foo(可能在您延迟初始化的映射中,其中键是函数参数的表示,就像std::pair<bool, bool>在这种情况下),或者使用一些引用计数的智能指针(boost::shared_ptr/std::shared_ptr在 C++11 中)保存newData如果您不想保留所有权(也将data成员包装在智能指针中)。

于 2013-02-26T05:35:39.313 回答
0

对我来说,这似乎是指针的用例。

让方法getData返回一个指针,如果您不想修改返回的对象,让它返回一个const指针。指针指向什么——成员数据或你动态创建的临时数据——可以在运行时决定。这也将避免在方法返回时复制数据。

在这种方法中,您需要注意的一件事是您创建的临时数据必须在堆上,否则返回的指针将指向超出范围的内存。

于 2013-02-26T07:13:46.217 回答