Return Value Optimization (RVO) and NRVO
Return Value Optimization (RVO) and Named Return Value Optimization (NRVO) are powerful compiler techniques that eliminate unnecessary copies or moves when returning objects from functions. By allowing the compiler to construct the return value directly in the memory space of the caller, these optimizations make move semantics even more efficient. This means that, in many cases, neither a copy nor a move constructor will be called when a function returns a local object.
main.cpp
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152// Demonstrate RVO and move constructor calls #include <iostream> #include <string> class Widget { public: std::string name; Widget(const std::string& n) : name(n) { std::cout << "Constructed: " << name << '\n'; } Widget(const Widget& other) : name(other.name) { std::cout << "Copied: " << name << '\n'; } Widget(Widget&& other) noexcept : name(std::move(other.name)) { std::cout << "Moved: " << name << '\n'; } ~Widget() { std::cout << "Destroyed: " << name << '\n'; } }; // Function that returns a temporary (RVO applies) Widget makeWidgetRVO() { return Widget("RVO"); } // Function that returns a named local (NRVO may apply) Widget makeWidgetNRVO() { Widget w("NRVO"); return w; } // Function that disables RVO/NRVO (forces move) Widget makeWidgetNoRVO() { Widget w("No RVO"); // Returning via std::move disables RVO/NRVO return std::move(w); } int main() { std::cout << "-- RVO Test --\n"; Widget a = makeWidgetRVO(); std::cout << "-- NRVO Test --\n"; Widget b = makeWidgetNRVO(); std::cout << "-- No RVO Test --\n"; Widget c = makeWidgetNoRVO(); }
Watch the output to see if the move constructor is called. With RVO or NRVO, the compiler may construct the return value directly in the caller’s memory, skipping both move and copy constructors for efficiency.
Since C++17, RVO is mandatory in some cases, though NRVO remains an optimization. These optimizations make move constructors less common in practice, but you should still implement them for correctness and performance.
Whether RVO or NRVO occurs can depend on compiler settings and optimization levels, so behavior might vary between different builds or compilers.
Дякуємо за ваш відгук!
Запитати АІ
Запитати АІ
Запитайте про що завгодно або спробуйте одне із запропонованих запитань, щоб почати наш чат
Чудово!
Completion показник покращився до 10
Return Value Optimization (RVO) and NRVO
Свайпніть щоб показати меню
Return Value Optimization (RVO) and Named Return Value Optimization (NRVO) are powerful compiler techniques that eliminate unnecessary copies or moves when returning objects from functions. By allowing the compiler to construct the return value directly in the memory space of the caller, these optimizations make move semantics even more efficient. This means that, in many cases, neither a copy nor a move constructor will be called when a function returns a local object.
main.cpp
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152// Demonstrate RVO and move constructor calls #include <iostream> #include <string> class Widget { public: std::string name; Widget(const std::string& n) : name(n) { std::cout << "Constructed: " << name << '\n'; } Widget(const Widget& other) : name(other.name) { std::cout << "Copied: " << name << '\n'; } Widget(Widget&& other) noexcept : name(std::move(other.name)) { std::cout << "Moved: " << name << '\n'; } ~Widget() { std::cout << "Destroyed: " << name << '\n'; } }; // Function that returns a temporary (RVO applies) Widget makeWidgetRVO() { return Widget("RVO"); } // Function that returns a named local (NRVO may apply) Widget makeWidgetNRVO() { Widget w("NRVO"); return w; } // Function that disables RVO/NRVO (forces move) Widget makeWidgetNoRVO() { Widget w("No RVO"); // Returning via std::move disables RVO/NRVO return std::move(w); } int main() { std::cout << "-- RVO Test --\n"; Widget a = makeWidgetRVO(); std::cout << "-- NRVO Test --\n"; Widget b = makeWidgetNRVO(); std::cout << "-- No RVO Test --\n"; Widget c = makeWidgetNoRVO(); }
Watch the output to see if the move constructor is called. With RVO or NRVO, the compiler may construct the return value directly in the caller’s memory, skipping both move and copy constructors for efficiency.
Since C++17, RVO is mandatory in some cases, though NRVO remains an optimization. These optimizations make move constructors less common in practice, but you should still implement them for correctness and performance.
Whether RVO or NRVO occurs can depend on compiler settings and optimization levels, so behavior might vary between different builds or compilers.
Дякуємо за ваш відгук!