C++ 对成员或临时成员的常量引用

C++ 对成员或临时成员的常量引用,c++,reference,constants,C++,Reference,Constants,我有一个类,它包含我希望经常使用的数据,所以我认为最好返回对它的常量引用。但是,给定一些参数,我可能需要动态创建新数据。我已经看到,可以将临时引用返回到常量引用,如下所示: class Foo { public: Foo() { ... } //Initialize data LARGE_DATA getData(bool param1, bool param2) { if (...) {

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

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)
}
但这似乎会复制
数据
。我想这样做:

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)
}

所以要避免不必要的拷贝。VisualStudio对此没有抱怨,但g++有抱怨(而且可能是正确的)。正确的方法是什么?

在返回引用之前,您可能应该通过在
Foo
中的某个位置存储
newData
来保留所有权(可能是在一个映射中,您懒散地初始化该映射,其中键是函数参数的表示形式,如本例中的
std::pair
),或者使用一些引用计数智能指针(
boost::shared_ptr
/
std::shared_ptr
,在C++11中)来保存
新数据(如果不想保留所有权,还可以将
数据
成员包装在智能指针中)(C++11中的
boost::shared_ptr
/
std::shared_ptr
)来保存
新数据,如果您不想保留所有权(还将
数据
成员包装在智能指针中)。

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

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


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

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

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


在这种方法中,你需要小心的是你创建的临时数据必须堆,否则返回的指针将指向超出范围的内存。

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

您的第二个实现试图通过返回引用来阻止复制
数据
,但这与g++不同,因为
newData
。您不再返回名为
newData
的临时对象,而是返回对它的引用,根据g++,该引用不符合生存期扩展的条件


我认为有两种方法可以解决这个问题。您可以中断
getData()
分为两种方法,一种通过返回引用返回
数据,另一种通过值返回
newData
,以便创建临时。或者,您可以将
newData
保存为类的数据成员,像返回
数据
一样返回对该数据的引用,并在每次需要时将其覆盖重新计算它,但是如果你只需要在一个给定代码的值下读取<代码> NeXDATA <代码>,在连续调用到“代码> GETDATA())/> >

< P>我想我理解你的困境。在你的第一个实现中,你依赖于C++的一个特性,在这里描述了一个临时的(<代码> NeXDATA</代码>)当调用函数将从函数返回的常量引用保存在堆栈上时,该函数的生存期将延长。但如果返回的是
data
,而不是
newData
,它将创建一个副本,然后将该副本作为临时副本返回,这是您不想要的

您的第二个实现试图通过返回引用来阻止复制
数据
,但这与g++不同,因为
newData
。您不再返回名为
newData
的临时对象,而是返回对它的引用,根据g++,该引用不符合生存期扩展的条件


我认为有两种方法可以解决这个问题。您可以中断
getData()
分为两种方法,一种通过返回引用返回
数据,另一种通过值返回
newData
,以便创建临时。或者,您可以将
newData
保存为类的数据成员,像返回
数据
一样返回对该数据的引用,并在每次需要时将其覆盖重新计算它,但仅当在连续调用
getData()之间只需要读取
newData
的给定值时,此操作才有效

由于我更喜欢确定是使用旧数据还是创建新数据来留在这个类中的逻辑,我可能会选择第二个选项。这可能不是最好的解决方案,因为该方法的性质对于常量对象应该是安全的,但现在这对我来说并不重要。谢谢!因为我会优先考虑逻辑