Const对成员或临时的引用

时间:2013-02-26 05:25:56

标签: c++ reference const

我有一个包含我期望使用的数据的类,所以我认为最好返回一个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 ++确实(并且可能是这样)。什么是正确的方法?

3 个答案:

答案 0 :(得分:1)

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

您的第二个实现尝试通过返回引用来阻止复制data,但由于newData,这会因g ++而中断。您不再返回名为newData的临时对象,您现在正在返回对它的引用,根据g ++,它不符合终身扩展的条件。

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

答案 1 :(得分:0)

你应该通过在newData中的某个位置存储Foo来保留所有权,然后再返回对它的引用(可能在你懒洋洋地初始化的地图中,其中键是函数参数的表示,比如在这种情况下为std::pair<bool, bool>,或者使用一些引用计数智能指针(C ++ 11中的boost::shared_ptr / std::shared_ptr)来保存newData如果您不想保留所有权(也将data成员包装在智能指针中)。

答案 2 :(得分:0)

对我而言,它似乎是指针的用例。

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

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