Топ питань
Часова шкала
Чат
Перспективи
Поліпшення повернення значення
З Вікіпедії, вільної енциклопедії
Remove ads
Поліпшення повернення значення (англ. return value optimization, RVO) чи просто ППЗ — це техніка оптимізації, яку застосовує компілятор, що серед іншого виключає створення тимчасового об'єкта для збереження значення, що вертається з функції.[1] В C++, вона особливо примітна тим, що дозволяє змінити поведінку отриманої програми.[2]
Підсумок
Узагальнити
Перспектива
Загалом, стандарт С++ дозволяє компіляторам застосовувати будь-які оптимізації, допоки отриманий виконуваний файл поводиться так, наче всі вимоги стандарту було виконано. Цей підхід зазвичай згадується як правило "так наче" (англ. as-if rule).[3] Термін поліпшення повернення значення звертається до пункту в ISO/IEC 14882, який дозволяє реалізації опустити копіювання, що відбувається через інструкцію повернення, навіть якщо конструктор копіювання має побічні ефекти,[4], хоча це й не дозволяється самим правилом так наче.[3]
Наступний приклад показує хід дій, за якого реалізація може позбутись одного чи двох копіювань, навіть якщо конструктор копіювання має видимі побічні ефекти, приміром, роздрук тексту.[4] Перше копіювання якого можна уникнути - копіювання створеного екземпляру класу C()
у значення, що поверне функція f
. Друге - копіювання тимчасового об'єкта повернутого функцією f
у obj
.
#include <iostream>
struct C {
C() {}
C(const C&) { std::cout << "Відбулось копіювання.\n"; }
};
C f() {
return C();
}
int main() {
std::cout << "Здоровенькі були!\n";
C obj = f();
}
Залежно від компілятора та його налаштувань, програма може вивести такий текст:
Здоровенькі були! Відбулось копіювання. Відбулось копіювання.
Здоровенькі були! Відбулось копіювання.
Здоровенькі були!
Remove ads
Пояснення
Узагальнити
Перспектива
При повернені вбудованого типу з функції додаткових операцій зазвичай не виконується, оскільки об'єкт передається через регістр. Вертання більших об'єктів (екземпляру деякого класу) може вимагати копіювання з однієї місцини в пам'яті до іншої. Для цього у стековому кадрі створюється прихований об'єкт, адреса якого передається у функцію. Значення що повертається з функції копіюється в цей об'єкт за наданою адресою.[5] Отже, для коду на кшталт:
struct Data {
char bytes[16];
};
Data f() {
Data result = {};
// утворення результату
return result;
}
int main() {
Data d = f();
}
компілятор згенерує таке:
struct Data {
char bytes[16];
};
Data * f(Data * _hiddenAddress) {
Data result = {};
// копіювання результату в прихований об'єкт
*_hiddenAddress = result;
return _hiddenAddress;
}
int main() {
Data _hidden; // створити прихований об'єкт
Data d = *f(&_hidden); // копіювати результат в d
}
Як бачимо, двічі виконується копіювання об'єкта Data
.
На ранніх стадіях розвитку C++, нездатність мови ефективно повернути об'єкт класу з функції вважалась одним з її недоліків.[6] Близько 1991, Волтер Брайт винайшов спосіб зменшення кількості копіювань, використовуючи замість двох об'єктів (прихованого та локальної змінної функції f) один - у який зберігається результат:[7]
struct Data {
char bytes[16];
};
void f(Data *p) {
// записуємо результат одразу в *p
}
int main() {
Data d;
f(&d);
}
Брайт реалізував своє поліпшення в компіляторі Zortech C++.[6] Цей особливий спосіб був з часом названий «Поліпшення повернення іменованого значення» (англ. named return value optimization), вказуючи на той факт, що копіювання іменованого об'єкта скасоване.[7]
Remove ads
Підтримка компіляторами
Поліпшення повернення значення підтримується більшістю компіляторів[1][8][9]. Однак можливі умови, коли компілятор не може виконати поліпшення. Найпоширенішим є приклад, коли функція повертає різні значення в залежності від шляху виконання програми: [8][10][5]
#include <string>
std::string f(bool cond = false) {
std::string first("first");
std::string second("second");
// функція може повернути один із двох іменованих об'єктів
// залежно від параметра. ППЗ не може бути застосоване
return cond ? first : second;
}
int main() {
std::string result = f();
}
Примітки
Wikiwand - on
Seamless Wikipedia browsing. On steroids.
Remove ads