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