With RVO we can return a local variable from a function without incurring the cost of a copy. Does this also work when returning a sub-object of variable?
From other answers I gather it does not when the complete object has a larger size than the object to be returned, as it would not fit in the space reserved for the return value. But what about the case where the complete object is otherwise "empty", i.e. the size is identical to the sub-object?
My rationale for asking this question:
Say I have a simple object
struct Data {
std::string s;
int i;
};
and a wrapper class which just acts as a more intelligent view of the data:
class WrapperRef {
Data& d;
public:
WrapperRef(Data& data) : d(data) {}
// some dummy functions operating on the data
char& foo() { return d.s[d.i]; }
};
This gets used internally by some functions returning Data
to ease implementation, but the interface doesn't reflect this (i.e. the functions don't return the wrapper itself). So I may have a function:
Data makeTheData(...) {
Data localData;
WrapperRef wrapper{localData};
// Manipulate the data using the wrapper
// ...
return localData;
}
Since this use case is common for my wrapper, I would like to replace this with a class that encapsulates it. I.e. I would replace the first two lines of makeTheData
with a single local object that contains a Data
sub-object and the functionality of the wrapper.
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;
}
This would help implementing the common use case for the wrapper. The ContainingWrapper
object has the same size as a Data
object, so RVO should be technically possible.
Can this functionality be achieved (with a member or base sub-object, or maybe different means) without losing the performance (which is crucial) of RVO? Does the as if rule apply and allow the optimizer to turn the second implementation of makeTheData
into the first, so that RVO is possible?