Fact-checked by Grok 2 weeks ago

Copy elision

Copy elision is a optimization technique in that allows the omission of copy and move constructions for objects of types under specific conditions, treating the source and target objects as identical even if the constructors or destructors exhibit observable side effects. This optimization is permitted in contexts such as return statements, throw expressions, parameters, and exception handlers, where one object is designated for destruction instead of two, ensuring that the program's observable behavior remains unchanged except for the number of constructions and destructions. The origins of copy elision trace back to a 1995 proposal by , which introduced "copy optimization" to eliminate unnecessary object copies in function returns and initializations as part of the evolving . Incorporated into the first (ISO/IEC 14882:1998), it initially focused on optional forms like return value optimization (RVO)—eliding copies of unnamed temporaries in return statements—and named return value optimization (NRVO)—extending this to named local variables—though implementation was not mandatory and depended on compiler heuristics. Prior to , copy elision was the sole permitted optimization altering program semantics in this manner; subsequent standards added allowances for move elision and allocation elision. Significant advancements occurred in C++17 with the adoption of guaranteed copy elision, which redefined prvalue materialization to mandate elision in cases like direct initialization from temporaries or prvalues, eliminating the need for copy or move constructors in those scenarios and enabling non-movable types to be returned efficiently. This change, driven by WG21 paper , simplified the language model by deferring temporary object creation until necessary, reducing overhead and improving code portability across compilers. However, elision remains prohibited in constant expressions and certain initialization contexts to preserve strict semantics.

Fundamentals

Definition and Mechanism

Copy elision is a optimization in C++ that allows the omission of copy or move constructors and destructors for objects under specific circumstances, even if those operations have observable side effects. In this , the object and the object as identical, constructing the object directly in its final storage location and adjusting the lifetime accordingly, thereby avoiding the creation of temporary objects. The mechanism of copy elision involves eliding the invocation of the copy or move constructor when a new object would otherwise be created from an existing one of the same type, provided the elision does not alter the observable of the program. For instance, if the first parameter of the selected constructor is an rvalue reference to the object's type, the destruction of that object occurs when the target would have been destroyed; otherwise, the destruction occurs at the later of the times when the two objects would have been destroyed without the optimization. This optimization is permitted only in non-constant expressions and is restricted in constant initialization contexts to preserve program semantics. Elidable copy contexts, as defined in the , include several scenarios where the compiler may or must omit such operations. These encompass the initialization of a as the result of a from a returning that 's type, where a non-volatile automatic object is directly constructed into the caller's return object. Another context is a throw-expression initializing an exception object from a non-volatile automatic object outside a try-block's . Additionally, in exception-declarations, the declared object may alias the exception object without copying, and since , coroutine parameters can elide copies if program meaning remains unchanged. Prior to , temporary materialization in copy-initialization could also be elided optionally. Copy elision has been part of the since C++98, where it was permitted but not required in cases like named return value optimization (NRVO). The standard expanded it to include throw-expressions and exception handlers, refining lifetime rules. In C++17, certain forms became mandatory through changes to prvalue semantics, guaranteeing elision for unnamed return value optimization (URVO) and temporary materializations without requiring copyable types, even if constructors are deleted. This shift ensures that copies or moves are elided when a temporary object is copied or moved to another object, provided it meets the elision criteria.

Performance Benefits

Copy elision offers substantial performance advantages by eliminating invocations of copy or move constructors, which are particularly costly for complex objects like strings or vectors that involve deep copying of internal data structures. This avoidance enables zero-cost abstractions, where the runtime overhead of returning or initializing objects by value matches that of direct construction, without the need for programmers to resort to less expressive reference or pointer semantics. Without copy elision, repeated object copies in scenarios such as loops or recursive functions can accumulate significant overhead, whereas elision constructs objects directly in their target locations, substantially reducing execution time. Additionally, it minimizes resource consumption by preventing the allocation of temporary objects and the corresponding calls to , thereby lowering both and CPU cycles dedicated to cleanup. Prior to , copy elision facilitated zero-copy returns through techniques like return value optimization, rendering value-based returns as efficient as returning references in terms of performance. This optimization ensured that even non-trivial objects could be returned without the expense of copying, promoting efficient value semantics across a wide range of applications.

Elision Contexts

Return Statements

In C++, copy elision applies to return statements when a returns an object by , allowing the to construct the object directly within the caller's designated return storage rather than creating a separate temporary and copying or moving it. This optimization is possible if the return expression names a local automatic object with automatic storage duration or a temporary object, thereby eliminating unnecessary constructor and destructor invocations. For elision to occur, the type of the return expression must match the function's return type exactly, disregarding only cv-qualifications such as const or volatile. Elision fails if the types differ or if the return involves user-defined conversions, including those via conversion constructors or operators, in which case a copy or move constructor must be invoked instead. This form of elision constitutes the core of return value optimization, a feature permitted by the since its 1998 edition. In cases of unnamed return values, such as return make_vector(); where the expression yields a prvalue, the may elide the copy prior to C++17, but this is not required and depends on the implementation. Starting with , such elision is guaranteed, as prvalues no longer materialize into temporaries but directly initialize the caller's return object.

Exception Handling

In the context of in C++, copy elision optimizes the propagation of exceptions by allowing the exception object to be constructed directly from the thrown expression, omitting any copy from a temporary, and by treating the catch handler's as an alias for the exception object, thereby avoiding a copy during the catch operation. This mechanism applies when the throw expression names a non-volatile automatic object with automatic storage duration (other than a function parameter or catch-clause parameter) of the same cv-unqualified type as the exception type and outside the scope of the innermost try-block, where the automatic object is constructed directly into the exception object. For prvalues in throw expressions, the exception object is directly initialized (since , without materializing a temporary), and no copy elision from a temporary is needed in the same manner. The conditions for in the catch handler require that the copy initialization of the handler from the exception object would not change the program's meaning beyond omitting constructors and destructors, typically when they share the same cv-unqualified type to avoid slicing or loss of information. For named automatic objects in throw expressions—non-volatile and outside the innermost try-block—the object can be constructed into the exception storage, provided it is not a or handler . This has been permitted since the C++98 standard, targeting the overhead in exception paths that, while infrequent, incur significant costs due to stack unwinding and object management. During propagation, particularly with rethrow statements (throw;), no additional copy occurs if the caught exception object was elided into the handler parameter, as the parameter acts as an alias for the original exception object, preserving its lifetime and state across handler boundaries. This aliasing ensures that modifications in the handler reflect back to the propagating exception, maintaining program semantics without invoking copy or move operations. Such optimizations reduce the runtime expense of exception handling, especially for complex objects, by minimizing constructor and destructor invocations along the error path.

Initializations

Copy elision in object initializations occurs when a omits the copy or move construction of a temporary object that would otherwise initialize a target object of the same type, constructing the temporary directly into the target's storage instead. This optimization is permitted under the when a temporary object, not bound to a , is copied or moved to a object with the same cv-unqualified type as the temporary. By treating the source and target as a single object, the avoids unnecessary constructions while preserving the observable behavior, including side effects from constructors or destructors that are elided. A common case arises in direct initialization where a prvalue expression produces a temporary that initializes an object of the same type. For instance, in the declaration Foo f(g());—assuming g() returns a prvalue of type Foo—the temporary resulting from g() can be elided, allowing direct into f without invoking a copy or move constructor. This applies similarly to copy initialization forms like Foo f = g();, where the temporary from the prvalue is constructed straight into the target object, reducing overhead in scenarios involving function calls or complex expressions that yield temporaries. Such is particularly beneficial for expensive-to-construct types, as it eliminates the double construction that would otherwise occur. Elision also extends to initialization lists, including member and base initializers in constructors, where temporaries passed as arguments can be bound directly to the target subobjects if they share the same type. In a constructor's initializer list, if a temporary expression of type T initializes a member or base of type T, the may construct the temporary directly into that subobject, omitting the copy or move. This rule ensures that temporaries in constructor arguments are not redundantly copied when they align with the target's lifetime and type requirements. The introduction of uniform initialization in C++11 further clarified and enhanced copy elision opportunities for braced-init-lists, enabling direct construction in list-initialization contexts that would previously involve additional copies. Under C++11's list-initialization rules, when a braced-init-list selects a copy or move constructor for the target type, elision can occur by constructing the elements directly into the object, thus reducing copies in aggregate and initializations. This clarification promotes more efficient uniform syntax, such as Foo f{args};, where temporaries from the initializer integrate seamlessly without intermediate objects. Overall, these mechanisms ensure that initializations leveraging temporaries remain performant by prioritizing direct binding over explicit copies or moves.

Optimizations and Variants

Return Value Optimization

Return Value Optimization (RVO) refers to a specific instance of copy elision applied when a function returns an unnamed temporary object or prvalue by value, allowing the compiler to construct the object directly in the caller's designated return storage location rather than creating and copying a temporary. This eliminates the invocation of the copy or move constructor that would typically occur, thereby avoiding unnecessary overhead in object construction and destruction. The mechanism behind RVO often involves the passing a hidden pointer or to the return slot—allocated by the caller—as an implicit to the , enabling direct into that without intermediate temporaries. This approach may require whole-program analysis to identify eligible return expressions or reliance on standardized calling conventions that support return-by-invisible- semantics for non-trivial types. By sharing between the callee and caller, RVO ensures the returned object's lifetime aligns with the caller's expectations, mimicking the efficiency of returning a while preserving value semantics. Unlike broader forms of copy elision, RVO is narrowly focused on return-by-value scenarios to achieve performance comparable to pass-by-reference, without altering the function's interface or introducing dangling reference risks. It has been a permitted optimization in the since the 1998 specification, with widespread implementation in major compilers by the late , though its application could vary based on factors like function inlining or optimization levels. Prior to , RVO for unnamed returns was optional; since then, it has become mandatory for prvalues, ensuring consistent elision across compliant compilers.

Named Return Value Optimization

Named Return Value Optimization (NRVO) is a form of copy elision that allows compilers to construct a named local object directly into the caller's return slot when it is returned from a , thereby omitting the subsequent copy or move operation. This optimization applies specifically to functions returning types by , where the return statement's expression is the name of a non-volatile object with storage duration that is neither a nor an exception-declaration . By treating the local object and the function's result object as identical, NRVO avoids the invocation of copy or move constructors and destructors that would otherwise occur. For NRVO to occur, the returned named object must typically be the same across all execution paths in the function, as compilers rely on analysis to ensure the optimization preserves program semantics. Elision is permitted by the whenever the return expression meets the basic criteria, but practical often fails in cases involving conditional returns of different objects, loops that alias the object, or that complicates lifetime tracking. Additionally, the object should not be modified in ways that introduce side effects incompatible with direct construction into the return slot, such as taking its for external use before return. Compared to Return Value Optimization for unnamed temporaries, NRVO is more conservative because it involves a that may have aliases or conditional usage, necessitating deeper flow analysis by the to verify elision safety. Despite these constraints, NRVO extends opportunities to scenarios with complex local computations where unnamed returns are impractical. In contemporary s like , , and MSVC, NRVO is routinely combined with other techniques to maximize performance in return-heavy code, though it remains optional and may be disabled in debug builds or via flags like /Zc:nrvo-.

Standards Evolution

Pre-C++11 Specifications

Copy elision was introduced in the C++98 standard (ISO/IEC 14882:1998) as an optional optimization technique specified in section 12.8, paragraph 15, allowing compilers to omit certain copy constructions of class objects even when the copy constructor or destructor exhibited side effects. In such cases, the implementation could treat the source and target of the elided copy as aliases for the same object, with destruction occurring as if the object were constructed only once. This provision enabled efficient implementation of value semantics, permitting objects to be passed and returned by value without invariably incurring the overhead of copying, while leaving the decision to elide to the compiler's discretion. The standard explicitly permitted elision in three primary contexts, which could be combined to eliminate multiple copies: first, in a return statement of a function returning a type, when the returned expression named a non-volatile automatic object (other than a or catch-clause ) with the same cv-unqualified type as the return type, allowing direct construction into the return value; second, when a temporary object not bound to a reference would be copied to another object of the same cv-unqualified type, permitting direct construction of the temporary into the target; and third, in a throw-expression, when the thrown named a non-volatile automatic object (other than a or catch-clause ) with the same cv-unqualified type as the exception object, allowing direct construction into the exception. These rules applied only to non-volatile objects with automatic storage duration and did not extend to constant expressions or constant initializations. Key limitations in the C++98 and subsequent standards restricted elision's applicability, particularly prohibiting it for most named objects outside the specified return and throw contexts, thereby relying on optional techniques such as Return Value Optimization (RVO) for unnamed temporaries and Named Return Value Optimization (NRVO) for named locals. was further barred for volatile objects, function parameters, and catch-clause parameters, ensuring that observable behavior remained consistent unless explicitly elided within the permitted cases. This permissive framework balanced optimization opportunities with predictable program semantics, though it meant that programmers could not rely on elision for performance guarantees.

C++11 and Later Changes

In , the language introduced rvalue references and move semantics, which provided a mechanism to efficiently transfer resources from temporary objects without deep copying when copy elision could not be applied. This interacted with copy elision such that elided copies or moves were skipped entirely, even if std::move was explicitly applied to force a move; the optimization precedence ensured no unnecessary constructor calls occurred. also permitted copy elision in exception handlers, allowing the omission of copy-initialization when the handler's parameter is initialized from a matching non-volatile automatic object of the same type. As a result, developers could rely on elision to avoid overhead in return statements and initializations, with moves serving as a fallback only when elision was unavailable. C++14 built on these foundations by permitting allocation elision alongside traditional copy elision as an allowed optimization, reducing overhead in object construction and destruction. Refinements to uniform initialization, originally introduced in C++11, further enabled elision of additional temporaries in list-initialization contexts, such as when initializing aggregates or using braced-init-lists, by treating them more uniformly without implicit conversions that might trigger copies. If elision failed in these scenarios, automatic move semantics ensured that rvalue-like behavior was invoked preferentially over copying, minimizing runtime costs for movable types. The most significant evolution occurred in C++17, which mandated guaranteed copy elision for prvalues in specific contexts, such as return statements and variable initializations from prvalue expressions. Under these rules, prvalues are no longer materialized as temporary objects but are constructed directly into the storage of their target, eliminating any potential copy or move operations. This guarantee applies particularly to returning prvalues from functions, where the returned object is built in the caller's return slot without intermediate temporaries. Elision's precedence over move semantics means that even non-movable or non-copyable types can participate without requiring move constructors, as no such operations are semantically required, thereby extending the optimization's applicability to a broader range of user-defined types. C++20 extended copy elision to coroutine contexts, permitting the omission of copies for coroutine parameters that are non-volatile automatic objects with the same cv-unqualified type as the parameter.

Compiler Implementations

Major Compilers

GCC has supported full return value optimization (RVO) and named return value optimization (NRVO) since version 4.1, with these optimizations enabled by default and controllable via the -fno-elide-constructors flag. As of GCC 14 (2023), further NRVO enhancements improve elision in more complex cases. In C++17 mode, GCC provides guaranteed copy elision as required by the standard starting from version 7, indicated by the predefined macro __cpp_guaranteed_copy_elision with value 201606L. Clang implements aggressive copy elision, including NRVO in most cases, since version 3.0, aligning closely with the C++ standard's permissions for optional optimizations. For C++17's guaranteed copy elision (P0135R1), support was added in 4.0, ensuring prvalue expressions are constructed directly in their target storage without temporary materialization. Microsoft Visual C++ (MSVC) has included RVO at least since Visual Studio 2005, with improvements to NRVO implementation in Visual Studio 2015, allowing more consistent elision for named local variables returned from functions. Full support for C++17 guaranteed copy elision arrived in 2017 (version 15.6), where mandatory elision occurs regardless of optimization settings, while optional NRVO can be explicitly controlled via the /Zc:nrvo flag introduced in Visual Studio 2022 version 17.4. All major C++ compilers—GCC, Clang, and MSVC—enable copy elision by default without requiring special flags, though higher optimization levels such as -O2 or /O2 typically enhance the scope and aggressiveness of these optimizations by enabling additional passes that identify elision opportunities.

Verification Methods

To verify whether copy elision is occurring in a C++ program, developers can use compiler flags to disable the optimization and compare the resulting behavior against the default enabled case. In and , the -fno-elide-constructors flag disables copy elision, forcing the compiler to invoke copy or move constructors even in scenarios where elision would otherwise apply, such as return value optimization. By compiling the same code with and without this flag—typically under optimization levels like -O2—and observing differences in execution (e.g., via output or runtime metrics), one can confirm if elision was active in the optimized build. Debugging techniques provide direct observation of constructor invocations to confirm . A common method involves instrumenting the copy and move constructors of the class in question with statements, counters, or side-effect producing (such as incrementing a or to stdout) to track how many times they are called during program execution. If occurs, these instrumented functions will not be invoked for the elided copies, allowing through ; this approach is particularly useful when combined with the -fno-elide-constructors to establish a where calls are expected. Static analysis tools and compiler warnings offer compile-time detection of potential elision issues or missed opportunities. Clang emits warnings such as "moving a local object in a prevents copy " when code patterns (e.g., using std::move on a return operand) inhibit , helping identify cases where optimization might not apply. Similarly, GCC's -Wpessimizing-move flag warns about std::move usage that blocks in return contexts. Tools like -Tidy can further assist through checks such as performance-unnecessary-copy-initialization, which flags redundant copies that could avoid, though it focuses more on initialization patterns than directly. In C++17 and later, guaranteed copy elision for prvalues makes the behavior observable without relying on optional optimizations, as prvalues initialize objects directly without materializing temporaries, eliding any copy or move even if constructors have side effects. This can be verified using side-effect tests, such as placing observable actions (e.g., or counter increments) in the copy/move constructors and confirming they are not executed when returning a prvalue, distinguishing it from pre-C++17 optional elision where side effects might inconsistently appear.

Practical Examples

Simple Return Case

In the simple return case, a function returns a prvalue, such as a temporary object created by an expression like a constructor call or operation result, without involving named local variables. Copy elision permits the to omit the copy (or move) of this temporary by constructing it directly into the caller's designated storage, as specified in the C++ standard's copy elision rules. This optimization, often realized through return value optimization (RVO), reduces overhead by eliminating unnecessary object creations and destructions. A representative example involves a function returning the result of a temporary concatenation, demonstrated using a custom Str that mimics basic behavior and tracks constructions and copies via static counters:
cpp
#include <iostream>
#include <cstring>

struct Str {
    static int construct_count;
    static int copy_count;
    char* data;
    Str(const char* s) : data(new char[strlen(s) + 1]) {
        strcpy(data, s);
        ++construct_count;
        std::cout << "Construction\n";
    }
    Str(const Str& other) : data(new char[strlen(other.data) + 1]) {
        strcpy(data, other.data);
        ++copy_count;
        std::cout << "Copy construction\n";
    }
    Str operator+(const Str& other) const {
        size_t len = strlen(data) + strlen(other.data) + 1;
        char* new_data = new char[len];
        strcpy(new_data, data);
        strcat(new_data, other.data);
        Str result(new_data);
        delete[] new_data;  // Temporary allocation for + result
        return result;
    }
    ~Str() {
        delete[] data;
        std::cout << "Destruction\n";
    }
};

int Str::construct_count = 0;
int Str::copy_count = 0;

Str make_concat() {
    Str temp1("hello");
    Str temp2(" world");
    return temp1 + temp2;  // Returns temporary from operator+
}

int main() {
    Str result = make_concat();
    std::cout << "Final counts - Constructs: " << Str::construct_count
              << ", Copies: " << Str::copy_count << "\n";
    return 0;
}
In this code, make_concat constructs two temporary Str objects, concatenates them to produce another temporary via operator+, and returns that result. With copy elision enabled (the default in modern compilers), the returned temporary is constructed directly into result, yielding output such as:
Construction
Construction
Construction
Destruction
Destruction
Destruction
Final counts - Constructs: 3, Copies: 0
Here, the three constructions correspond to temp1, temp2, and the direct construction of result (eliding the copy from the + temporary); the three destructions follow their scopes. Without elision (e.g., compiled with GCC's -fno-elide-constructors flag), an additional copy construction occurs for the returned temporary into result, producing:
Construction
Construction
Construction
Copy construction
Destruction
Destruction
Destruction
Destruction
Final counts - Constructs: 3, Copies: 1
The extra copy and destruction reflect the unelided temporary. This case achieves zero copies for the return in eliding mode and is compatible with C++98, where such elision was permitted (though optional) to optimize performance even in early standards. In C++17 and later, elision becomes guaranteed for prvalue returns like this temporary, ensuring consistent zero-copy behavior across compliant compilers.

Exception Case

In exception handling, copy elision can occur when an exception object is thrown and subsequently caught by value, allowing the compiler to omit the copy construction of the catch parameter from the exception object. This optimization treats the catch clause's parameter as an alias for the exception object itself, provided the types match (ignoring cv-qualifiers) and no observable behavior changes except for omitted constructor and destructor calls. Consider the following example, where a class MyException logs its constructors and destructor to illustrate the elision:
cpp
#include <iostream>

class MyException {
public:
    MyException(const std::string& msg) : message(msg) {
        std::cout << "Constructor called with: " << message << std::endl;
    }
    MyException(const MyException& other) : message(other.message) {
        std::cout << "Copy constructor called" << std::endl;
    }
    std::string getMessage() const { return message; }
    ~MyException() {
        std::cout << "Destructor called" << std::endl;
    }
private:
    std::string message;
};

void riskyFunction() {
    try {
        throw MyException("Error occurred!");
    } catch (MyException e) {
        std::cout << "Caught: " << e.getMessage() << std::endl;
    }
}
When riskyFunction is executed with copy elision enabled (as permitted by the C++ standard), the output typically shows only one constructor call for the temporary exception object, which is directly used as the exception object and aliased by the catch parameter e, followed by a single destructor call at the end of the scope. Without elision, an additional copy constructor would be invoked to initialize e from the exception object, and an extra destructor would run for the temporary, demonstrating the performance benefit of omitting these operations. If the caught exception is rethrown using throw;, further copy elision applies: the rethrow expression elides any copy or move from the current exception object to a new one, constructing the new exception directly in the caller's context. In a non-elided scenario for rethrow (e.g., in older compilers or specific configurations), an extra copy constructor and destructor pair would appear, highlighting the overhead avoided by this optimization. This case underscores the value of copy elision in exception paths, where avoiding copies of potentially large or expensive-to-construct objects can improve efficiency, particularly in performance-sensitive applications involving frequent error conditions.

Initialization Case

In the initialization case of copy elision, a class object is copy-initialized from a prvalue (pure rvalue) expression of the same type, allowing the compiler to construct the object directly in the target storage without creating an intermediate temporary or invoking the copy or move constructor. This optimization applies when the initializer is a nameless temporary, such as in variable declarations or constructor calls where a temporary is passed by value. Consider the following example, where a class Foo tracks constructor invocations via output:
cpp
#include <iostream>

class Foo {
public:
    Foo() { std::cout << "default constructor\n"; }
    Foo(const Foo&) { std::cout << "copy constructor\n"; }
    Foo(Foo&&) { std::cout << "move constructor\n"; }
    ~Foo() { std::cout << "destructor\n"; }
};

int main() {
    Foo f = Foo();  // Copy-initialization from a prvalue
}
Without , this would construct a temporary Foo object using the default constructor, then invoke the copy or move constructor to initialize f from that temporary, followed by two destructors. With copy elision, only the default constructor is called once for f directly, and one destructor executes at the end. The same principle extends to constructor arguments passed by value; for instance, in void func(Foo param); func(Foo());, the prvalue Foo() is constructed directly into param's storage, eliding any copy or move into the . Prior to , this elision was permitted but not guaranteed, potentially leading to a copy or move in some implementations. C++11 introduced uniform initialization syntax (using braces {}), which facilitates similar elisions and often reduces temporaries compared to pre-C++11 parenthesized styles; for example, Foo f{Foo()}; behaves equivalently to the copy-initialization form but avoids implicit type conversions that might create extra objects in older code. This form of copy elision is common in patterns, where objects manage resources via constructors; direct construction ensures efficient resource acquisition without unnecessary copies, preserving and performance.

References

  1. [1]
    [class.copy.elision]
    ### Definition and Key Points
  2. [2]
  3. [3]
    Guaranteed copy elision through simplified value categories
    The approach we take to provide guaranteed copy elision is to tweak the definition of C++'s 'glvalue' and 'prvalue' value categories (which, ...
  4. [4]
  5. [5]
  6. [6]
  7. [7]
  8. [8]
    Trip report: Summer ISO C++ standards meeting (Oulu) - Herb Sutter
    Jun 30, 2016 · Guaranteed copy elision: When you call a function that returns an object by value, and you use the copy to initialize a local variable, the ...
  9. [9]
    Wording for guaranteed copy elision through simplified value ...
    Jun 20, 2016 · This paper provides wording for P0135R0. This also resolves the following core issues: 1565: Copy elision and lifetime of initializer_list ...
  10. [10]
    [PDF] N4663.pdf - Standard C++
    Mar 25, 2017 · ISO/IEC 14882:2014 is hereafter called the C++ Standard. Beginning ... whether copy elision will occur. It determines the constructor ...
  11. [11]
  12. [12]
  13. [13]
    [PDF] Technical Report on Performance Issues - Open Standards
    Apr 19, 2000 · •= Use the return value optimization to give the compiler a hint that temporary objects can be eliminated. The trick is to return ...<|control11|><|separator|>
  14. [14]
  15. [15]
    Return value optimization (RVO) - sigcpp
    Jun 8, 2020 · Return-value optimization is a compiler technique to avoid copying an object that a function returns as its value, including avoiding creation of a temporary ...
  16. [16]
    Optimize Options (Using the GNU Compiler Collection (GCC))
    Do not substitute constants for known return value of formatted output functions ... Increasing this arbitrarily chosen value means more aggressive optimization ...
  17. [17]
    C++ Standard Core Language Defect Reports and Accepted Issues
    ... This elision of copy operations is permitted in the following circumstances (which may be combined to eliminate multiple copies):. in a return statement in a ...<|control11|><|separator|>
  18. [18]
  19. [19]
    Guaranteed Copy Elision Does Not Elide Copies - C++ Team Blog
    Dec 11, 2018 · The standard allows this copy to be elided by constructing the return value at the call-site rather than in make ( C++11 [class.copy]/31 ).
  20. [20]
    C++ Dialect Options (Using the GNU Compiler Collection (GCC))
    ### Summary of Copy Elision, RVO, NRVO in GCC
  21. [21]
    C++ Standards Support in GCC - GNU Project
    C++17 Support in GCC. GCC has almost full support for the 2017 revision of ... Guaranteed copy elision, P0135R1 · 7, __cpp_guaranteed_copy_elision >= 201606.
  22. [22]
    Clang - C++ Programming Language Status - LLVM
    Clang has support for some of the features of the C++ standard following C++23, informally referred to as C++26. You can use Clang in C++2c mode with the -std= ...
  23. [23]
    Microsoft C/C++ change history 2003 - 2015
    Oct 3, 2025 · This article describes all the breaking changes from Visual Studio 2015 going back to Visual Studio 2003.
  24. [24]
    /Zc:nrvo (Control optional NRVO) | Microsoft Learn
    Nov 15, 2022 · The C++ standard allows (but doesn't require) the compiler to optionally construct the returned object directly in the return slot of the ...
  25. [25]
    Clang Compiler User's Manual — Clang 22.0.0git documentation
    This document describes important notes about using Clang as a compiler for an end-user, documenting the supported features, command line options, etc.
  26. [26]
    Clang command line argument reference — Clang 22.0.0git documentation
    ### Summary of Clang Command Line Reference (Related to Copy Elision)
  27. [27]
    Diagnostic flags in Clang - LLVM
    This page lists the diagnostic flags currently supported by Clang. Diagnostic flags -W Synonym for -Wextra. -W#pragma-messages This diagnostic is enabled by ...
  28. [28]
    clang-tidy - performance-unnecessary-copy-initialization
    When an expensive to copy variable is copy initialized by the return value from a type on this list the check does not trigger. This can be used to exclude ...Missing: elision | Show results with:elision
  29. [29]
    Improving Copy and Move Elision - C++ Team Blog
    Oct 24, 2022 · However, changes to inlining decisions, dead code elimination, and other optimizations can change whether copy or move elision is possible.<|control11|><|separator|>