From Jason Turner

[class.copy.elision]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpxmgy77oc/{from.md → to.md} +44 -51
tmp/tmpxmgy77oc/{from.md → to.md} RENAMED
@@ -8,13 +8,15 @@ source and target of the omitted copy/move operation as simply two
8
  different ways of referring to the same object. If the first parameter
9
  of the selected constructor is an rvalue reference to the object’s type,
10
  the destruction of that object occurs when the target would have been
11
  destroyed; otherwise, the destruction occurs at the later of the times
12
  when the two objects would have been destroyed without the
13
- optimization.[^14] This elision of copy/move operations, called *copy
14
- elision*, is permitted in the following circumstances (which may be
15
- combined to eliminate multiple copies):
 
 
16
 
17
  - in a `return` statement in a function with a class return type, when
18
  the *expression* is the name of a non-volatile object with automatic
19
  storage duration (other than a function parameter or a variable
20
  introduced by the *exception-declaration* of a *handler*
@@ -22,14 +24,14 @@ combined to eliminate multiple copies):
22
  the function return type, the copy/move operation can be omitted by
23
  constructing the object directly into the function call’s return
24
  object
25
  - in a *throw-expression* [[expr.throw]], when the operand is the name
26
  of a non-volatile object with automatic storage duration (other than a
27
- function or catch-clause parameter) whose scope does not extend beyond
28
- the end of the innermost enclosing *try-block* (if there is one), the
29
- copy/move operation can be omitted by constructing the object directly
30
- into the exception object
31
  - in a coroutine [[dcl.fct.def.coroutine]], a copy of a coroutine
32
  parameter can be omitted and references to that copy replaced with
33
  references to the corresponding parameter if the meaning of the
34
  program will be unchanged except for the execution of a constructor
35
  and destructor for the parameter copy object
@@ -45,12 +47,12 @@ combined to eliminate multiple copies):
45
 
46
  Copy elision is not permitted where an expression is evaluated in a
47
  context requiring a constant expression [[expr.const]] and in constant
48
  initialization [[basic.start.static]].
49
 
50
- [*Note 2*: Copy elision might be performed if the same expression is
51
- evaluated in another context. — *end note*]
52
 
53
  [*Example 1*:
54
 
55
  ``` cpp
56
  class Thing {
@@ -79,54 +81,25 @@ constexpr A g() {
79
 
80
  constexpr A a; // well-formed, a.p points to a
81
  constexpr A b = g(); // error: b.p would be dangling[expr.const]
82
 
83
  void h() {
84
- A c = g(); // well-formed, c.p may point to c or to an ephemeral temporary
85
  }
86
  ```
87
 
88
  Here the criteria for elision can eliminate the copying of the object
89
  `t` with automatic storage duration into the result object for the
90
- function call `f()`, which is the global object `t2`. Effectively, the
91
- construction of the local object `t` can be viewed as directly
92
- initializing the global object `t2`, and that object’s destruction will
93
- occur at program exit. Adding a move constructor to `Thing` has the same
94
- effect, but it is the move construction from the object with automatic
95
- storage duration to `t2` that is elided.
96
 
97
  — *end example*]
98
 
99
- An *implicitly movable entity* is a variable of automatic storage
100
- duration that is either a non-volatile object or an rvalue reference to
101
- a non-volatile object type. In the following copy-initialization
102
- contexts, a move operation might be used instead of a copy operation:
103
-
104
- - If the *expression* in a `return` [[stmt.return]] or `co_return`
105
- [[stmt.return.coroutine]] statement is a (possibly parenthesized)
106
- *id-expression* that names an implicitly movable entity declared in
107
- the body or *parameter-declaration-clause* of the innermost enclosing
108
- function or *lambda-expression*, or
109
- - if the operand of a *throw-expression* [[expr.throw]] is a (possibly
110
- parenthesized) *id-expression* that names an implicitly movable entity
111
- whose scope does not extend beyond the *compound-statement* of the
112
- innermost *try-block* or *function-try-block* (if any) whose
113
- *compound-statement* or *ctor-initializer* encloses the
114
- *throw-expression*,
115
-
116
- overload resolution to select the constructor for the copy or the
117
- `return_value` overload to call is first performed as if the expression
118
- or operand were an rvalue. If the first overload resolution fails or was
119
- not performed, overload resolution is performed again, considering the
120
- expression or operand as an lvalue.
121
-
122
- [*Note 3*: This two-stage overload resolution must be performed
123
- regardless of whether copy elision will occur. It determines the
124
- constructor or the `return_value` overload to be called if elision is
125
- not performed, and the selected constructor or `return_value` overload
126
- must be accessible even if the call is elided. — *end note*]
127
-
128
  [*Example 2*:
129
 
130
  ``` cpp
131
  class Thing {
132
  public:
@@ -138,24 +111,44 @@ private:
138
  };
139
 
140
  Thing f(bool b) {
141
  Thing t;
142
  if (b)
143
- throw t; // OK: Thing(Thing&&) used (or elided) to throw t
144
- return t; // OK: Thing(Thing&&) used (or elided) to return t
145
  }
146
 
147
- Thing t2 = f(false); // OK: no extra copy/move performed, t2 constructed by call to f
148
 
149
  struct Weird {
150
  Weird();
151
  Weird(Weird&);
152
  };
153
 
154
- Weird g() {
155
- Weird w;
156
- return w; // OK: first overload resolution fails, second overload resolution selects Weird(Weird&)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  }
158
  ```
159
 
160
  — *end example*]
161
 
 
8
  different ways of referring to the same object. If the first parameter
9
  of the selected constructor is an rvalue reference to the object’s type,
10
  the destruction of that object occurs when the target would have been
11
  destroyed; otherwise, the destruction occurs at the later of the times
12
  when the two objects would have been destroyed without the
13
+ optimization.[^14]
14
+
15
+ This elision of copy/move operations, called *copy elision*, is
16
+ permitted in the following circumstances (which may be combined to
17
+ eliminate multiple copies):
18
 
19
  - in a `return` statement in a function with a class return type, when
20
  the *expression* is the name of a non-volatile object with automatic
21
  storage duration (other than a function parameter or a variable
22
  introduced by the *exception-declaration* of a *handler*
 
24
  the function return type, the copy/move operation can be omitted by
25
  constructing the object directly into the function call’s return
26
  object
27
  - in a *throw-expression* [[expr.throw]], when the operand is the name
28
  of a non-volatile object with automatic storage duration (other than a
29
+ function or catch-clause parameter) that belongs to a scope that does
30
+ not contain the innermost enclosing *compound-statement* associated
31
+ with a *try-block* (if there is one), the copy/move operation can be
32
+ omitted by constructing the object directly into the exception object
33
  - in a coroutine [[dcl.fct.def.coroutine]], a copy of a coroutine
34
  parameter can be omitted and references to that copy replaced with
35
  references to the corresponding parameter if the meaning of the
36
  program will be unchanged except for the execution of a constructor
37
  and destructor for the parameter copy object
 
47
 
48
  Copy elision is not permitted where an expression is evaluated in a
49
  context requiring a constant expression [[expr.const]] and in constant
50
  initialization [[basic.start.static]].
51
 
52
+ [*Note 2*: It is possible that copy elision is performed if the same
53
+ expression is evaluated in another context. — *end note*]
54
 
55
  [*Example 1*:
56
 
57
  ``` cpp
58
  class Thing {
 
81
 
82
  constexpr A a; // well-formed, a.p points to a
83
  constexpr A b = g(); // error: b.p would be dangling[expr.const]
84
 
85
  void h() {
86
+ A c = g(); // well-formed, c.p can point to c or be dangling
87
  }
88
  ```
89
 
90
  Here the criteria for elision can eliminate the copying of the object
91
  `t` with automatic storage duration into the result object for the
92
+ function call `f()`, which is the non-local object `t2`. Effectively,
93
+ the construction of `t` can be viewed as directly initializing `t2`, and
94
+ that object’s destruction will occur at program exit. Adding a move
95
+ constructor to `Thing` has the same effect, but it is the move
96
+ construction from the object with automatic storage duration to `t2`
97
+ that is elided.
98
 
99
  — *end example*]
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  [*Example 2*:
102
 
103
  ``` cpp
104
  class Thing {
105
  public:
 
111
  };
112
 
113
  Thing f(bool b) {
114
  Thing t;
115
  if (b)
116
+ throw t; // OK, Thing(Thing&&) used (or elided) to throw t
117
+ return t; // OK, Thing(Thing&&) used (or elided) to return t
118
  }
119
 
120
+ Thing t2 = f(false); // OK, no extra copy/move performed, t2 constructed by call to f
121
 
122
  struct Weird {
123
  Weird();
124
  Weird(Weird&);
125
  };
126
 
127
+ Weird g(bool b) {
128
+ static Weird w1;
129
+ Weird w2;
130
+ if (b)
131
+ return w1; // OK, uses Weird(Weird&)
132
+ else
133
+ return w2; // error: w2 in this context is an xvalue
134
+ }
135
+
136
+ int& h(bool b, int i) {
137
+ static int s;
138
+ if (b)
139
+ return s; // OK
140
+ else
141
+ return i; // error: i is an xvalue
142
+ }
143
+
144
+ decltype(auto) h2(Thing t) {
145
+ return t; // OK, t is an xvalue and h2's return type is Thing
146
+ }
147
+
148
+ decltype(auto) h3(Thing t) {
149
+ return (t); // OK, (t) is an xvalue and h3's return type is Thing&&
150
  }
151
  ```
152
 
153
  — *end example*]
154