Поліпшення повернення значення (англ. return value optimization, RVO) чи просто ППЗ — це техніка оптимізації, яку застосовує компілятор, що серед іншого виключає створення для збереження значення, що вертається з функції. В , вона особливо примітна тим, що дозволяє змінити поведінку отриманої програми.
Підсумок
Загалом, стандарт С++ дозволяє компіляторам застосовувати будь-які оптимізації, допоки отриманий виконуваний файл поводиться так, наче всі вимоги стандарту було виконано. Цей підхід зазвичай згадується як правило "так наче" (англ. as-if rule). Термін поліпшення повернення значення звертається до пункту в ISO/IEC 14882, який дозволяє реалізації опустити копіювання, що відбувається через інструкцію повернення, навіть якщо конструктор копіювання має побічні ефекти,, хоча це й не дозволяється самим правилом так наче.
Наступний приклад показує хід дій, за якого реалізація може позбутись одного чи двох копіювань, навіть якщо конструктор копіювання має видимі побічні ефекти, приміром, роздрук тексту. Перше копіювання якого можна уникнути - копіювання створеного екземпляру класу 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(); }
Залежно від компілятора та його налаштувань, програма може вивести такий текст:
Здоровенькі були! Відбулось копіювання. Відбулось копіювання.
Здоровенькі були! Відбулось копіювання.
Здоровенькі були!
Пояснення
При повернені вбудованого типу з функції додаткових операцій зазвичай не виконується, оскільки об'єкт передається через регістр. Вертання більших об'єктів (екземпляру деякого класу) може вимагати копіювання з однієї місцини в пам'яті до іншої. Для цього у стековому кадрі створюється прихований об'єкт, адреса якого передається у функцію. Значення що повертається з функції копіюється в цей об'єкт за наданою адресою. Отже, для коду на кшталт:
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
.
На ранніх стадіях розвитку , нездатність мови ефективно повернути об'єкт класу з функції вважалась одним з її недоліків. Близько 1991, Волтер Брайт винайшов спосіб зменшення кількості копіювань, використовуючи замість двох об'єктів (прихованого та локальної змінної функції f) один - у який зберігається результат:
struct Data { char bytes[16]; }; void f(Data *p) { // записуємо результат одразу в *p } int main() { Data d; f(&d); }
Брайт реалізував своє поліпшення в компіляторі Zortech C++. Цей особливий спосіб був з часом названий «Поліпшення повернення іменованого значення» (англ. named return value optimization), вказуючи на той факт, що копіювання іменованого об'єкта скасоване.
Підтримка компіляторами
Поліпшення повернення значення підтримується більшістю компіляторів. Однак можливі умови, коли компілятор не може виконати поліпшення. Найпоширенішим є приклад, коли функція повертає різні значення в залежності від шляху виконання програми:
#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(); }
Примітки
- Meyers, Scott (1996). More Effective C++. Addison Wesley.
- Alexandrescu, Andrei (1 лютого 2003). Move Constructors. . Архів оригіналу за 14 липня 2013. Процитовано 25 березня 2009.
- ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §1.9 Program execution [intro.execution] para. 1
- ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §12.8 Copying class objects [class.copy] para. 15
- Bulka, Dov; David Mayhew (2000). Efficient C++. Addison-Wesley. ISBN .
- Lippman, Stan. The Name Return Value Optimization. Stan Lippman. Архів оригіналу за 14 липня 2013. Процитовано 23 березня 2009.
- Glossary D Programming Language 2.0. Digital Mars. Архів оригіналу за 14 липня 2013. Процитовано 23 березня 2009.
- Shoukry, Ayman B. Named Return Value Optimization in Visual C++ 2005. Microsoft. Архів оригіналу за 14 липня 2013. Процитовано 20 березня 2009.
- Options Controlling C++ Dialect. GCC. 17 березня 2001. Архів оригіналу за 14 липня 2013. Процитовано 20 березня 2009.
- Hinnant, Howard; et al. (10 вересня 2002). . WG21. Архів оригіналу за 8 лютого 2007. Процитовано 25 березня 2009.
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
Polipshennya povernennya znachennya angl return value optimization RVO chi prosto PPZ ce tehnika optimizaciyi yaku zastosovuye kompilyator sho sered inshogo viklyuchaye stvorennya dlya zberezhennya znachennya sho vertayetsya z funkciyi V C vona osoblivo primitna tim sho dozvolyaye zminiti povedinku otrimanoyi programi PidsumokZagalom standart S dozvolyaye kompilyatoram zastosovuvati bud yaki optimizaciyi dopoki otrimanij vikonuvanij fajl povoditsya tak nache vsi vimogi standartu bulo vikonano Cej pidhid zazvichaj zgaduyetsya yak pravilo tak nache angl as if rule Termin polipshennya povernennya znachennya zvertayetsya do punktu v ISO IEC 14882 yakij dozvolyaye realizaciyi opustiti kopiyuvannya sho vidbuvayetsya cherez instrukciyu povernennya navit yaksho konstruktor kopiyuvannya maye pobichni efekti hocha ce j ne dozvolyayetsya samim pravilom tak nache Nastupnij priklad pokazuye hid dij za yakogo realizaciya mozhe pozbutis odnogo chi dvoh kopiyuvan navit yaksho konstruktor kopiyuvannya maye vidimi pobichni efekti primirom rozdruk tekstu Pershe kopiyuvannya yakogo mozhna uniknuti kopiyuvannya stvorenogo ekzemplyaru klasu C u znachennya sho poverne funkciya f Druge kopiyuvannya timchasovogo ob yekta povernutogo funkciyeyu f u obj include lt iostream gt struct C C C const C amp std cout lt lt Vidbulos kopiyuvannya n C f return C int main std cout lt lt Zdorovenki buli n C obj f Zalezhno vid kompilyatora ta jogo nalashtuvan programa mozhe vivesti takij tekst Zdorovenki buli Vidbulos kopiyuvannya Vidbulos kopiyuvannya Zdorovenki buli Vidbulos kopiyuvannya Zdorovenki buli PoyasnennyaPri poverneni vbudovanogo tipu z funkciyi dodatkovih operacij zazvichaj ne vikonuyetsya oskilki ob yekt peredayetsya cherez registr Vertannya bilshih ob yektiv ekzemplyaru deyakogo klasu mozhe vimagati kopiyuvannya z odniyeyi miscini v pam yati do inshoyi Dlya cogo u stekovomu kadri stvoryuyetsya prihovanij ob yekt adresa yakogo peredayetsya u funkciyu Znachennya sho povertayetsya z funkciyi kopiyuyetsya v cej ob yekt za nadanoyu adresoyu Otzhe dlya kodu na kshtalt struct Data char bytes 16 Data f Data result utvorennya rezultatu return result int main Data d f kompilyator zgeneruye take struct Data char bytes 16 Data f Data hiddenAddress Data result kopiyuvannya rezultatu v prihovanij ob yekt hiddenAddress result return hiddenAddress int main Data hidden stvoriti prihovanij ob yekt Data d f amp hidden kopiyuvati rezultat v d Yak bachimo dvichi vikonuyetsya kopiyuvannya ob yekta Data Na rannih stadiyah rozvitku C nezdatnist movi efektivno povernuti ob yekt klasu z funkciyi vvazhalas odnim z yiyi nedolikiv Blizko 1991 Volter Brajt vinajshov sposib zmenshennya kilkosti kopiyuvan vikoristovuyuchi zamist dvoh ob yektiv prihovanogo ta lokalnoyi zminnoyi funkciyi f odin u yakij zberigayetsya rezultat struct Data char bytes 16 void f Data p zapisuyemo rezultat odrazu v p int main Data d f amp d Brajt realizuvav svoye polipshennya v kompilyatori Zortech C Cej osoblivij sposib buv z chasom nazvanij Polipshennya povernennya imenovanogo znachennya angl named return value optimization vkazuyuchi na toj fakt sho kopiyuvannya imenovanogo ob yekta skasovane Pidtrimka kompilyatoramiPolipshennya povernennya znachennya pidtrimuyetsya bilshistyu kompilyatoriv Odnak mozhlivi umovi koli kompilyator ne mozhe vikonati polipshennya Najposhirenishim ye priklad koli funkciya povertaye rizni znachennya v zalezhnosti vid shlyahu vikonannya programi include lt string gt std string f bool cond false std string first first std string second second funkciya mozhe povernuti odin iz dvoh imenovanih ob yektiv zalezhno vid parametra PPZ ne mozhe buti zastosovane return cond first second int main std string result f PrimitkiMeyers Scott 1996 More Effective C Addison Wesley Alexandrescu Andrei 1 lyutogo 2003 Move Constructors Arhiv originalu za 14 lipnya 2013 Procitovano 25 bereznya 2009 ISO IEC 2003 ISO IEC 14882 2003 E Programming Languages C 1 9 Program execution intro execution para 1 ISO IEC 2003 ISO IEC 14882 2003 E Programming Languages C 12 8 Copying class objects class copy para 15 Bulka Dov David Mayhew 2000 Efficient C Addison Wesley ISBN 0 201 37950 3 Lippman Stan The Name Return Value Optimization Stan Lippman Arhiv originalu za 14 lipnya 2013 Procitovano 23 bereznya 2009 Glossary D Programming Language 2 0 Digital Mars Arhiv originalu za 14 lipnya 2013 Procitovano 23 bereznya 2009 Shoukry Ayman B Named Return Value Optimization in Visual C 2005 Microsoft Arhiv originalu za 14 lipnya 2013 Procitovano 20 bereznya 2009 Options Controlling C Dialect GCC 17 bereznya 2001 Arhiv originalu za 14 lipnya 2013 Procitovano 20 bereznya 2009 Hinnant Howard et al 10 veresnya 2002 WG21 Arhiv originalu za 8 lyutogo 2007 Procitovano 25 bereznya 2009