С помощью 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? Применяется ли правило как если бы и позволяет ли оптимизатору превратить вторую реализацию makeTheData
в первую, чтобы стало возможным RVO?