From Jason Turner

[basic.life]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp6g2ds0js/{from.md → to.md} +52 -30
tmp/tmp6g2ds0js/{from.md → to.md} RENAMED
@@ -1,12 +1,17 @@
1
  ### Lifetime <a id="basic.life">[[basic.life]]</a>
2
 
 
 
 
3
  The *lifetime* of an object or reference is a runtime property of the
4
  object or reference. A variable is said to have *vacuous initialization*
5
- if it is default-initialized and, if it is of class type or a (possibly
6
- multidimensional) array thereof, that class type has a trivial default
7
- constructor. The lifetime of an object of type `T` begins when:
 
 
8
 
9
  - storage with the proper alignment and size for type `T` is obtained,
10
  and
11
  - its initialization (if any) is complete (including vacuous
12
  initialization) [[dcl.init]],
@@ -21,10 +26,29 @@ except as described in [[allocator.members]]. The lifetime of an object
21
  - if `T` is a non-class type, the object is destroyed, or
22
  - if `T` is a class type, the destructor call starts, or
23
  - the storage which the object occupies is released, or is reused by an
24
  object that is not nested within *o* [[intro.object]].
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  The lifetime of a reference begins when its initialization is complete.
27
  The lifetime of a reference ends as if it were a scalar object requiring
28
  storage.
29
 
30
  [*Note 1*: [[class.base.init]] describes the lifetime of base and
@@ -53,22 +77,22 @@ In this case, the destructor is not implicitly invoked.
53
 
54
  [*Note 4*: The correct behavior of a program often depends on the
55
  destructor being invoked for each object of class type. — *end note*]
56
 
57
  Before the lifetime of an object has started but after the storage which
58
- the object will occupy has been allocated[^8]
59
 
60
- or, after the lifetime of an object has ended and before the storage
61
  which the object occupied is reused or released, any pointer that
62
  represents the address of the storage location where the object will be
63
  or was located may be used but only in limited ways. For an object under
64
  construction or destruction, see  [[class.cdtor]]. Otherwise, such a
65
  pointer refers to allocated storage [[basic.stc.dynamic.allocation]],
66
  and using the pointer as if the pointer were of type `void*` is
67
  well-defined. Indirection through such a pointer is permitted but the
68
  resulting lvalue may only be used in limited ways, as described below.
69
- The program has undefined behavior if:
70
 
71
  - the pointer is used as the operand of a *delete-expression*,
72
  - the pointer is used to access a non-static data member or call a
73
  non-static member function of the object, or
74
  - the pointer is implicitly converted [[conv.ptr]] to a pointer to a
@@ -78,11 +102,11 @@ The program has undefined behavior if:
78
  cv `void`, or to pointer to cv `void` and subsequently to pointer to
79
  cv `char`, cv `unsigned char`, or cv `std::byte` [[cstddef.syn]], or
80
  - the pointer is used as the operand of a `dynamic_cast`
81
  [[expr.dynamic.cast]].
82
 
83
- [*Example 1*:
84
 
85
  ``` cpp
86
  #include <cstdlib>
87
 
88
  struct B {
@@ -111,36 +135,32 @@ void g() {
111
  ```
112
 
113
  — *end example*]
114
 
115
  Similarly, before the lifetime of an object has started but after the
116
- storage which the object will occupy has been allocated or, after the
117
  lifetime of an object has ended and before the storage which the object
118
  occupied is reused or released, any glvalue that refers to the original
119
  object may be used but only in limited ways. For an object under
120
  construction or destruction, see  [[class.cdtor]]. Otherwise, such a
121
  glvalue refers to allocated storage [[basic.stc.dynamic.allocation]],
122
  and using the properties of the glvalue that do not depend on its value
123
- is well-defined. The program has undefined behavior if:
124
 
125
  - the glvalue is used to access the object, or
126
  - the glvalue is used to call a non-static member function of the
127
  object, or
128
  - the glvalue is bound to a reference to a virtual base class
129
  [[dcl.init.ref]], or
130
  - the glvalue is used as the operand of a `dynamic_cast`
131
  [[expr.dynamic.cast]] or as the operand of `typeid`.
132
 
133
- If, after the lifetime of an object has ended and before the storage
134
- which the object occupied is reused or released, a new object is created
135
- at the storage location which the original object occupied, a pointer
136
- that pointed to the original object, a reference that referred to the
137
- original object, or the name of the original object will automatically
138
- refer to the new object and, once the lifetime of the new object has
139
- started, can be used to manipulate the new object, if the original
140
- object is transparently replaceable (see below) by the new object. An
141
- object o₁ is *transparently replaceable* by an object o₂ if:
142
 
143
  - the storage that o₂ occupies exactly overlays the storage that o₁
144
  occupied, and
145
  - o₁ and o₂ are of the same type (ignoring the top-level cv-qualifiers),
146
  and
@@ -149,11 +169,20 @@ object o₁ is *transparently replaceable* by an object o₂ if:
149
  [[intro.object]], and
150
  - either o₁ and o₂ are both complete objects, or o₁ and o₂ are direct
151
  subobjects of objects p₁ and p₂, respectively, and p₁ is transparently
152
  replaceable by p₂.
153
 
154
- [*Example 2*:
 
 
 
 
 
 
 
 
 
155
 
156
  ``` cpp
157
  struct C {
158
  int i;
159
  void f();
@@ -175,25 +204,25 @@ c1 = c2; // well-defined
175
  c1.f(); // well-defined; c1 refers to a new object of type C
176
  ```
177
 
178
  — *end example*]
179
 
180
- [*Note 5*: If these conditions are not met, a pointer to the new object
181
  can be obtained from a pointer that represents the address of its
182
  storage by calling `std::launder` [[ptr.launder]]. — *end note*]
183
 
184
  If a program ends the lifetime of an object of type `T` with static
185
  [[basic.stc.static]], thread [[basic.stc.thread]], or automatic
186
  [[basic.stc.auto]] storage duration and if `T` has a non-trivial
187
- destructor,[^9]
188
 
189
  and another object of the original type does not occupy that same
190
  storage location when the implicit destructor call takes place, the
191
  behavior of the program is undefined. This is true even if the block is
192
  exited with an exception.
193
 
194
- [*Example 3*:
195
 
196
  ``` cpp
197
  class T { };
198
  struct B {
199
  ~B();
@@ -210,11 +239,11 @@ void h() {
210
  Creating a new object within the storage that a const, complete object
211
  with static, thread, or automatic storage duration occupies, or within
212
  the storage that such a const object used to occupy before its lifetime
213
  ended, results in undefined behavior.
214
 
215
- [*Example 4*:
216
 
217
  ``` cpp
218
  struct B {
219
  B();
220
  ~B();
@@ -228,12 +257,5 @@ void h() {
228
  }
229
  ```
230
 
231
  — *end example*]
232
 
233
- In this subclause, “before” and “after” refer to the “happens before”
234
- relation [[intro.multithread]].
235
-
236
- [*Note 6*: Therefore, undefined behavior results if an object that is
237
- being constructed in one thread is referenced from another thread
238
- without adequate synchronization. — *end note*]
239
-
 
1
  ### Lifetime <a id="basic.life">[[basic.life]]</a>
2
 
3
+ In this subclause, “before” and “after” refer to the “happens before”
4
+ relation [[intro.multithread]].
5
+
6
  The *lifetime* of an object or reference is a runtime property of the
7
  object or reference. A variable is said to have *vacuous initialization*
8
+ if it is default-initialized, no other initialization is performed, and,
9
+ if it is of class type or a (possibly multidimensional) array thereof, a
10
+ trivial constructor of that class type is selected for the
11
+ default-initialization. The lifetime of an object of type `T` begins
12
+ when:
13
 
14
  - storage with the proper alignment and size for type `T` is obtained,
15
  and
16
  - its initialization (if any) is complete (including vacuous
17
  initialization) [[dcl.init]],
 
26
  - if `T` is a non-class type, the object is destroyed, or
27
  - if `T` is a class type, the destructor call starts, or
28
  - the storage which the object occupies is released, or is reused by an
29
  object that is not nested within *o* [[intro.object]].
30
 
31
+ When evaluating a *new-expression*, storage is considered reused after
32
+ it is returned from the allocation function, but before the evaluation
33
+ of the *new-initializer* [[expr.new]].
34
+
35
+ [*Example 1*:
36
+
37
+ ``` cpp
38
+ struct S {
39
+ int m;
40
+ };
41
+
42
+ void f() {
43
+ S x{1};
44
+ new(&x) S(x.m); // undefined behavior
45
+ }
46
+ ```
47
+
48
+ — *end example*]
49
+
50
  The lifetime of a reference begins when its initialization is complete.
51
  The lifetime of a reference ends as if it were a scalar object requiring
52
  storage.
53
 
54
  [*Note 1*: [[class.base.init]] describes the lifetime of base and
 
77
 
78
  [*Note 4*: The correct behavior of a program often depends on the
79
  destructor being invoked for each object of class type. — *end note*]
80
 
81
  Before the lifetime of an object has started but after the storage which
82
+ the object will occupy has been allocated[^7]
83
 
84
+ or after the lifetime of an object has ended and before the storage
85
  which the object occupied is reused or released, any pointer that
86
  represents the address of the storage location where the object will be
87
  or was located may be used but only in limited ways. For an object under
88
  construction or destruction, see  [[class.cdtor]]. Otherwise, such a
89
  pointer refers to allocated storage [[basic.stc.dynamic.allocation]],
90
  and using the pointer as if the pointer were of type `void*` is
91
  well-defined. Indirection through such a pointer is permitted but the
92
  resulting lvalue may only be used in limited ways, as described below.
93
+ The program has undefined behavior if
94
 
95
  - the pointer is used as the operand of a *delete-expression*,
96
  - the pointer is used to access a non-static data member or call a
97
  non-static member function of the object, or
98
  - the pointer is implicitly converted [[conv.ptr]] to a pointer to a
 
102
  cv `void`, or to pointer to cv `void` and subsequently to pointer to
103
  cv `char`, cv `unsigned char`, or cv `std::byte` [[cstddef.syn]], or
104
  - the pointer is used as the operand of a `dynamic_cast`
105
  [[expr.dynamic.cast]].
106
 
107
+ [*Example 2*:
108
 
109
  ``` cpp
110
  #include <cstdlib>
111
 
112
  struct B {
 
135
  ```
136
 
137
  — *end example*]
138
 
139
  Similarly, before the lifetime of an object has started but after the
140
+ storage which the object will occupy has been allocated or after the
141
  lifetime of an object has ended and before the storage which the object
142
  occupied is reused or released, any glvalue that refers to the original
143
  object may be used but only in limited ways. For an object under
144
  construction or destruction, see  [[class.cdtor]]. Otherwise, such a
145
  glvalue refers to allocated storage [[basic.stc.dynamic.allocation]],
146
  and using the properties of the glvalue that do not depend on its value
147
+ is well-defined. The program has undefined behavior if
148
 
149
  - the glvalue is used to access the object, or
150
  - the glvalue is used to call a non-static member function of the
151
  object, or
152
  - the glvalue is bound to a reference to a virtual base class
153
  [[dcl.init.ref]], or
154
  - the glvalue is used as the operand of a `dynamic_cast`
155
  [[expr.dynamic.cast]] or as the operand of `typeid`.
156
 
157
+ [*Note 5*: Therefore, undefined behavior results if an object that is
158
+ being constructed in one thread is referenced from another thread
159
+ without adequate synchronization. *end note*]
160
+
161
+ An object o₁ is *transparently replaceable* by an object o₂ if
 
 
 
 
162
 
163
  - the storage that o₂ occupies exactly overlays the storage that o₁
164
  occupied, and
165
  - o₁ and o₂ are of the same type (ignoring the top-level cv-qualifiers),
166
  and
 
169
  [[intro.object]], and
170
  - either o₁ and o₂ are both complete objects, or o₁ and o₂ are direct
171
  subobjects of objects p₁ and p₂, respectively, and p₁ is transparently
172
  replaceable by p₂.
173
 
174
+ After the lifetime of an object has ended and before the storage which
175
+ the object occupied is reused or released, if a new object is created at
176
+ the storage location which the original object occupied and the original
177
+ object was transparently replaceable by the new object, a pointer that
178
+ pointed to the original object, a reference that referred to the
179
+ original object, or the name of the original object will automatically
180
+ refer to the new object and, once the lifetime of the new object has
181
+ started, can be used to manipulate the new object.
182
+
183
+ [*Example 3*:
184
 
185
  ``` cpp
186
  struct C {
187
  int i;
188
  void f();
 
204
  c1.f(); // well-defined; c1 refers to a new object of type C
205
  ```
206
 
207
  — *end example*]
208
 
209
+ [*Note 6*: If these conditions are not met, a pointer to the new object
210
  can be obtained from a pointer that represents the address of its
211
  storage by calling `std::launder` [[ptr.launder]]. — *end note*]
212
 
213
  If a program ends the lifetime of an object of type `T` with static
214
  [[basic.stc.static]], thread [[basic.stc.thread]], or automatic
215
  [[basic.stc.auto]] storage duration and if `T` has a non-trivial
216
+ destructor,[^8]
217
 
218
  and another object of the original type does not occupy that same
219
  storage location when the implicit destructor call takes place, the
220
  behavior of the program is undefined. This is true even if the block is
221
  exited with an exception.
222
 
223
+ [*Example 4*:
224
 
225
  ``` cpp
226
  class T { };
227
  struct B {
228
  ~B();
 
239
  Creating a new object within the storage that a const, complete object
240
  with static, thread, or automatic storage duration occupies, or within
241
  the storage that such a const object used to occupy before its lifetime
242
  ended, results in undefined behavior.
243
 
244
+ [*Example 5*:
245
 
246
  ``` cpp
247
  struct B {
248
  B();
249
  ~B();
 
257
  }
258
  ```
259
 
260
  — *end example*]
261