Copy elision explained

In C++ computer programming, copy elision refers to a compiler optimization technique that eliminates unnecessary copying of objects.

The C++ language standard generally allows implementations to perform any optimization, provided the resulting program's observable behavior is the same as if, i.e. pretending, the program were executed exactly as mandated by the standard. Beyond that, the standard also describes a few situations where copying can be eliminated even if this would alter the program's behavior, the most common being the return value optimization (see below). Another widely implemented optimization, described in the C++ standard, is when a temporary object of class type is copied to an object of the same type.[1] [2] As a result, copy-initialization is usually equivalent to direct-initialization in terms of performance, but not in semantics; copy-initialization still requires an accessible copy constructor.[3] The optimization can not be applied to a temporary object that has been bound to a reference.

Example

  1. include

int n = 0;

struct C ; // it modifies an object with static storage duration

int main

According to the standard a similar optimization may be applied to objects being thrown and caught,[4] [5] but it is unclear whether the optimization applies to both the copy from the thrown object to the exception object, and the copy from the exception object to the object declared in the exception-declaration of the catch clause. It is also unclear whether this optimization only applies to temporary objects, or named objects as well.[6] Given the following source code:

  1. include

struct C ;

void f // It is unclear whether this copy may be elided (omitted).

int main

A conforming compiler should therefore produce a program which prints "Hello World!" twice. In the C++11 revision of the C++ standard, the issues have been addressed, essentially allowing both the copy from the named object to the exception object, and the copy into the object declared in the exception handler to be elided.[6]

GCC provides the -fno-elide-constructors option to disable copy-elision. This option is useful to observe (or not observe) the effects of return value optimization or other optimizations where copies are elided. It is generally not recommended to disable this important optimization.

C++17 Provides for "guaranteed copy elision", a prvalue is not materialized until needed, and then it is constructed directly into the storage of its final destination.[7]

Return value optimization

In the context of the C++ programming language, return value optimization (RVO) is a compiler optimization that involves eliminating the temporary object created to hold a function's return value.[8] RVO is allowed to change the observable behaviour of the resulting program by the C++ standard.[9]

Summary

In general, the C++ standard allows a compiler to perform any optimization, provided the resulting executable exhibits the same observable behaviour as if (i.e. pretending) all the requirements of the standard have been fulfilled. This is commonly referred to as the "as-if rule".[10] [2] The term return value optimization refers to a special clause in the C++ standard that goes even further than the "as-if" rule: an implementation may omit a copy operation resulting from a return statement, even if the copy constructor has side effects.[11] [2]

The following example demonstrates a scenario where the implementation may eliminate one or both of the copies being made, even if the copy constructor has a visible side effect (printing text).[1] [2] The first copy that may be eliminated is the one where a nameless temporary C could be copied into the function f's return value. The second copy that may be eliminated is the copy of the temporary object returned by f to obj.

  1. include

struct C ;

C f

int main

Depending upon the compiler, and that compiler's settings, the resulting program may display any of the following outputs:

Hello World!
A copy was made.
A copy was made.
Hello World!
A copy was made.
Hello World!

Background

Returning an object of built-in type from a function usually carries little to no overhead, since the object typically fits in a CPU register. Returning a larger object of class type may require more expensive copying from one memory location to another. To avoid this, an implementation may create a hidden object in the caller's stack frame, and pass the address of this object to the function. The function's return value is then copied into the hidden object.[12] Thus, code such as this:

struct Data ;

Data F

int main

may generate code equivalent to this:

struct Data ;

Data* F(Data* _hiddenAddress)

int main

which causes the Data object to be copied twice.

In the early stages of the evolution of C++, the language's inability to efficiently return an object of class type from a function was considered a weakness.[13] Around 1991, Walter Bright implemented a technique to minimize copying, effectively replacing the hidden object and the named object inside the function with the object used for holding the result:[14]

struct Data ;

void F(Data* p)

int main

Bright implemented this optimization in his Zortech C++ compiler.[13] This particular technique was later coined "Named return value optimization" (NRVO), referring to the fact that the copying of a named object is elided.[14]

Compiler support

Return value optimization is supported on most compilers.[8] [15] [16] There may be, however, circumstances where the compiler is unable to perform the optimization. One common case is when a function may return different named objects depending on the path of execution:[12] [15] [17]

  1. include

std::string F(bool cond = false)

int main

External links

Notes and References

  1. [International Organization for Standardization|ISO]
  2. Book: ISO/IEC 14882:2003(E): Programming Languages - C++. . 2003 . https://web.archive.org/web/20230410154851/http://staff.ustc.edu.cn/~zhuang/cpp/specs/ISO_IEC%2014882%202003.pdf . 2023-04-10 . 2024-02-26 . § 12.8 Copying class objects [class.copy] . para. 15.
  3. Book: Herb. Sutter. Herb Sutter. 2001. More Exceptional C++. Addison-Wesley.
  4. [International Organization for Standardization|ISO]
  5. [International Organization for Standardization|ISO]
  6. Web site: C++ Standard Core Language Defect Reports. WG21. 2009-03-27.
  7. https://en.cppreference.com/w/cpp/language/copy_elision
  8. Book: Meyers, Scott . More Effective C++ . registration . Addison-Wesley . 1995. 9780201633719 .
  9. Web site: Move Constructors. Alexandrescu. Andrei. 2003-02-01. Dr. Dobb's Journal. 2009-03-25.
  10. [International Organization for Standardization|ISO]
  11. [International Organization for Standardization|ISO]
  12. Book: Bulka, Dov. David Mayhew . Efficient C++. Addison-Wesley. 2000. 0-201-37950-3.
  13. Web site: The Name Return Value Optimization . Lippman. Stan. Microsoft. 2004-02-03. 2009-03-23.
  14. Web site: Glossary D Programming Language 2.0. Digital Mars. 2009-03-23.
  15. Web site: Named Return Value Optimization in Visual C++ 2005 . Shoukry . Ayman B. . . October 2005 . 2009-03-20.
  16. Web site: Options Controlling C++ Dialect . 2001-03-17 . . 2018-01-20.
  17. Web site: N1377: A Proposal to Add Move Semantics Support to the C++ Language . Hinnant . Howard . 2002-09-10 . WG21 . 2009-03-25 . etal.