[class.copy.elision] (original) (raw)

11 Classes [class]

11.9 Initialization [class.init]

11.9.6 Copy/move elision [class.copy.elision]

When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object haveside effects.

In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object.

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.100

This elision of copy/move operations, calledcopy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies):

Copy elision is not permitted where an expression is evaluated in a context requiring a constant expression ([expr.const]) and in constant initialization ([basic.start.static]).

[Note 2:

It is possible that copy elision is performed if the same expression is evaluated in another context.

— _end note_]

[Example 1: class Thing { public: Thing();~Thing(); Thing(const Thing&);}; Thing f() { Thing t;return t;}Thing t2 = f();struct A { void *p;constexpr A(): p(this) {} };constexpr A g() { A loc;return loc;} constexpr A a; constexpr A b = g(); void h() { A c = g(); }

Here the criteria for elision can eliminate the copying of the object t with automatic storage duration into the result object for the function call f(), which is the non-local object t2.

Effectively, the construction of tcan be viewed as directly initializing t2, and that object's destruction will occur at program exit.

Adding a move constructor to Thing has the same effect, but it is the move construction from the object with automatic storage duration to t2 that is elided.

— _end example_]

[Example 2: class Thing { public: Thing();~Thing(); Thing(Thing&&);private: Thing(const Thing&);}; Thing f(bool b) { Thing t;if (b) throw t; return t; }Thing t2 = f(false); struct Weird { Weird(); Weird(Weird&);}; Weird g(bool b) { static Weird w1; Weird w2;if (b) return w1; else return w2; } int& h(bool b, int i) { static int s;if (b) return s; else return i; } decltype(auto) h2(Thing t) { return t; } decltype(auto) h3(Thing t) { return (t); } — _end example_]

[Example 3: template<class T> void g(const T&);template<class T> void f() { T x;try { T y;try { g(x); } catch (...) { if () throw x; throw y; } g(y);} catch(...) { g(x); g(y); } } — _end example_]