使用 RVO,我们可以从函数返回局部变量,而不会产生复制成本。这在返回变量的子对象时也有效吗?
从其他答案中,我收集到当完整对象的大小大于要返回的对象时,它不会,因为它不适合为返回值保留的空间。但是如果整个对象是“空的”,即大小与子对象相同,那又如何呢?
我问这个问题的理由:
假设我有一个简单的对象
struct Data {
std::string s;
int i;
};
和一个包装类,它只是作为数据的更智能视图:
class WrapperRef {
Data& d;
public:
WrapperRef(Data& data) : d(data) {}
// some dummy functions operating on the data
char& foo() { return d.s[d.i]; }
};
这被一些返回Data
以简化实现的函数在内部使用,但接口没有反映这一点(即函数不返回包装器本身)。所以我可能有一个功能:
Data makeTheData(...) {
Data localData;
WrapperRef wrapper{localData};
// Manipulate the data using the wrapper
// ...
return localData;
}
由于这个用例对于我的包装器来说很常见,我想用一个封装它的类来替换它。makeTheData
即,我将用包含Data
子对象和包装器功能的单个本地对象替换前两行。
class ContainingWrapper {
Data d;
public:
ContainingWrapper() = default;
// some dummy functions
char& foo() { return d.s[d.i]; }
// Convert to actual Data object. Maybe use other means instead such as a getter method?
operator Data&() { return d; }
};
Data makeTheData(...) {
ContainingWrapper wrapper;
// Manipulate the data using the wrapper
// ...
return wrapper;
}
这将有助于实现包装器的常见用例。该ContainingWrapper
对象与对象具有相同的大小Data
,因此 RVO 在技术上应该是可行的。
能否在不损失 RVO 性能(至关重要)的情况下实现此功能(使用成员或基础子对象,或者可能使用不同的方法)?as if规则是否适用并允许优化器将第二个实现makeTheData
转换为第一个实现,从而使 RVO 成为可能?