From Jason Turner

[basic.life]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpl4efa8et/{from.md → to.md} +73 -77
tmp/tmpl4efa8et/{from.md → to.md} RENAMED
@@ -1,90 +1,85 @@
1
- ## Object 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. An object is said to have *non-vacuous
5
- initialization* if it is of a class or aggregate type and it or one of
6
- its subobjects is initialized by a constructor other than a trivial
7
- default constructor.
8
-
9
- [*Note 1*: Initialization by a trivial copy/move constructor is
10
- non-vacuous initialization. — *end note*]
11
-
12
- The lifetime of an object of type `T` begins when:
13
 
14
  - storage with the proper alignment and size for type `T` is obtained,
15
  and
16
- - if the object has non-vacuous initialization, its initialization is
17
- complete,
18
 
19
  except that if the object is a union member or subobject thereof, its
20
  lifetime only begins if that union member is the initialized member in
21
  the union ([[dcl.init.aggr]], [[class.base.init]]), or as described in
22
- [[class.union]]. The lifetime of an object *o* of type `T` ends when:
 
 
23
 
24
- - if `T` is a class type with a non-trivial destructor (
25
- [[class.dtor]]), the destructor call starts, or
26
  - the storage which the object occupies is released, or is reused by an
27
- object that is not nested within *o* ([[intro.object]]).
28
 
29
  The lifetime of a reference begins when its initialization is complete.
30
- The lifetime of a reference ends as if it were a scalar object.
 
31
 
32
- [*Note 2*: [[class.base.init]] describes the lifetime of base and
33
  member subobjects. — *end note*]
34
 
35
  The properties ascribed to objects and references throughout this
36
- International Standard apply for a given object or reference only during
37
- its lifetime.
38
 
39
- [*Note 3*: In particular, before the lifetime of an object starts and
40
  after its lifetime ends there are significant restrictions on the use of
41
  the object, as described below, in  [[class.base.init]] and in 
42
  [[class.cdtor]]. Also, the behavior of an object under construction and
43
  destruction might not be the same as the behavior of an object whose
44
  lifetime has started and not ended. [[class.base.init]] and 
45
- [[class.cdtor]] describe the behavior of objects during the construction
46
- and destruction phases. — *end note*]
47
 
48
  A program may end the lifetime of any object by reusing the storage
49
- which the object occupies or by explicitly calling the destructor for an
50
- object of a class type with a non-trivial destructor. For an object of a
51
- class type with a non-trivial destructor, the program is not required to
52
- call the destructor explicitly before the storage which the object
53
- occupies is reused or released; however, if there is no explicit call to
54
- the destructor or if a *delete-expression* ([[expr.delete]]) is not
55
- used to release the storage, the destructor shall not be implicitly
56
- called and any program that depends on the side effects produced by the
57
- destructor has undefined behavior.
58
 
59
  Before the lifetime of an object has started but after the storage which
60
- the object will occupy has been allocated[^16] or, after the lifetime of
61
  an object has ended and before the storage which the object occupied is
62
  reused or released, any pointer that represents the address of the
63
  storage location where the object will be or was located may be used but
64
  only in limited ways. For an object under construction or destruction,
65
  see  [[class.cdtor]]. Otherwise, such a pointer refers to allocated
66
- storage ([[basic.stc.dynamic.deallocation]]), and using the pointer as
67
- if the pointer were of type `void*`, is well-defined. Indirection
68
- through such a pointer is permitted but the resulting lvalue may only be
69
- used in limited ways, as described below. The program has undefined
70
- behavior if:
71
 
72
  - the object will be or was of a class type with a non-trivial
73
  destructor and the pointer is used as the operand of a
74
  *delete-expression*,
75
  - the pointer is used to access a non-static data member or call a
76
  non-static member function of the object, or
77
- - the pointer is implicitly converted ([[conv.ptr]]) to a pointer to a
78
  virtual base class, or
79
- - the pointer is used as the operand of a `static_cast` (
80
- [[expr.static.cast]]), except when the conversion is to pointer to
81
  cv `void`, or to pointer to cv `void` and subsequently to pointer to
82
- cv `char`, cv `unsigned char`, or cv `std::byte` ([[cstddef.syn]]),
83
- or
84
- - the pointer is used as the operand of a `dynamic_cast` (
85
- [[expr.dynamic.cast]]).
86
 
87
  [*Example 1*:
88
 
89
  ``` cpp
90
  #include <cstdlib>
@@ -108,11 +103,11 @@ void g() {
108
  void* p = std::malloc(sizeof(D1) + sizeof(D2));
109
  B* pb = new (p) D1;
110
  pb->mutate();
111
  *pb; // OK: pb points to valid memory
112
  void* q = pb; // OK: pb points to valid memory
113
- pb->f(); // undefined behavior, lifetime of *pb has ended
114
  }
115
  ```
116
 
117
  — *end example*]
118
 
@@ -120,41 +115,42 @@ Similarly, before the lifetime of an object has started but after the
120
  storage which the object will occupy has been allocated or, after the
121
  lifetime of an object has ended and before the storage which the object
122
  occupied is reused or released, any glvalue that refers to the original
123
  object may be used but only in limited ways. For an object under
124
  construction or destruction, see  [[class.cdtor]]. Otherwise, such a
125
- glvalue refers to allocated storage (
126
- [[basic.stc.dynamic.deallocation]]), and using the properties of the
127
- glvalue that do not depend on its value is well-defined. The program has
128
- undefined behavior if:
129
 
130
  - the glvalue is used to access the object, or
131
  - the glvalue is used to call a non-static member function of the
132
  object, or
133
- - the glvalue is bound to a reference to a virtual base class (
134
- [[dcl.init.ref]]), or
135
- - the glvalue is used as the operand of a `dynamic_cast` (
136
- [[expr.dynamic.cast]]) or as the operand of `typeid`.
137
 
138
  If, after the lifetime of an object has ended and before the storage
139
  which the object occupied is reused or released, a new object is created
140
  at the storage location which the original object occupied, a pointer
141
  that pointed to the original object, a reference that referred to the
142
  original object, or the name of the original object will automatically
143
  refer to the new object and, once the lifetime of the new object has
144
- started, can be used to manipulate the new object, if:
 
 
145
 
146
- - the storage for the new object exactly overlays the storage location
147
- which the original object occupied, and
148
- - the new object is of the same type as the original object (ignoring
149
- the top-level cv-qualifiers), and
150
- - the type of the original object is not const-qualified, and, if a
151
- class type, does not contain any non-static data member whose type is
152
- const-qualified or a reference type, and
153
- - the original object was a most derived object ([[intro.object]]) of
154
- type `T` and the new object is a most derived object of type `T` (that
155
- is, they are not base class subobjects).
156
 
157
  [*Example 2*:
158
 
159
  ``` cpp
160
  struct C {
@@ -178,18 +174,18 @@ c1 = c2; // well-defined
178
  c1.f(); // well-defined; c1 refers to a new object of type C
179
  ```
180
 
181
  — *end example*]
182
 
183
- [*Note 4*: If these conditions are not met, a pointer to the new object
184
  can be obtained from a pointer that represents the address of its
185
- storage by calling `std::launder` ([[support.dynamic]]). — *end note*]
186
 
187
- If a program ends the lifetime of an object of type `T` with static (
188
- [[basic.stc.static]]), thread ([[basic.stc.thread]]), or automatic (
189
- [[basic.stc.auto]]) storage duration and if `T` has a non-trivial
190
- destructor,[^17] the program must ensure that an object of the original
191
  type occupies that same storage location when the implicit destructor
192
  call takes place; otherwise the behavior of the program is undefined.
193
  This is true even if the block is exited with an exception.
194
 
195
  [*Example 3*:
@@ -206,14 +202,14 @@ void h() {
206
  } // undefined behavior at block exit
207
  ```
208
 
209
  — *end example*]
210
 
211
- Creating a new object within the storage that a `const` complete object
212
  with static, thread, or automatic storage duration occupies, or within
213
- the storage that such a `const` object used to occupy before its
214
- lifetime ended, results in undefined behavior.
215
 
216
  [*Example 4*:
217
 
218
  ``` cpp
219
  struct B {
@@ -229,12 +225,12 @@ void h() {
229
  }
230
  ```
231
 
232
  — *end example*]
233
 
234
- In this section, “before” and “after” refer to the “happens before”
235
- relation ([[intro.multithread]]).
236
 
237
- [*Note 5*: Therefore, undefined behavior results if an object that is
238
  being constructed in one thread is referenced from another thread
239
  without adequate synchronization. — *end note*]
240
 
 
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
+ multi-dimensional) 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]],
13
 
14
  except that if the object is a union member or subobject thereof, its
15
  lifetime only begins if that union member is the initialized member in
16
  the union ([[dcl.init.aggr]], [[class.base.init]]), or as described in
17
+ [[class.union]] and [[class.copy.ctor]], and except as described in
18
+ [[allocator.members]]. The lifetime of an object *o* of type `T` ends
19
+ when:
20
 
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
31
  member subobjects. — *end note*]
32
 
33
  The properties ascribed to objects and references throughout this
34
+ document apply for a given object or reference only during its lifetime.
 
35
 
36
+ [*Note 2*: In particular, before the lifetime of an object starts and
37
  after its lifetime ends there are significant restrictions on the use of
38
  the object, as described below, in  [[class.base.init]] and in 
39
  [[class.cdtor]]. Also, the behavior of an object under construction and
40
  destruction might not be the same as the behavior of an object whose
41
  lifetime has started and not ended. [[class.base.init]] and 
42
+ [[class.cdtor]] describe the behavior of an object during its periods of
43
+ construction and destruction. — *end note*]
44
 
45
  A program may end the lifetime of any object by reusing the storage
46
+ which the object occupies or by explicitly calling a destructor or
47
+ pseudo-destructor [[expr.prim.id.dtor]] for the object. For an object of
48
+ a class type, the program is not required to call the destructor
49
+ explicitly before the storage which the object occupies is reused or
50
+ released; however, if there is no explicit call to the destructor or if
51
+ a *delete-expression* [[expr.delete]] is not used to release the
52
+ storage, the destructor is not implicitly called and any program that
53
+ depends on the side effects produced by the destructor has undefined
54
+ behavior.
55
 
56
  Before the lifetime of an object has started but after the storage which
57
+ the object will occupy has been allocated[^11] or, after the lifetime of
58
  an object has ended and before the storage which the object occupied is
59
  reused or released, any pointer that represents the address of the
60
  storage location where the object will be or was located may be used but
61
  only in limited ways. For an object under construction or destruction,
62
  see  [[class.cdtor]]. Otherwise, such a pointer refers to allocated
63
+ storage [[basic.stc.dynamic.allocation]], and using the pointer as if
64
+ the pointer were of type `void*` is well-defined. Indirection through
65
+ such a pointer is permitted but the resulting lvalue may only be used in
66
+ limited ways, as described below. The program has undefined behavior if:
 
67
 
68
  - the object will be or was of a class type with a non-trivial
69
  destructor and the pointer is used as the operand of a
70
  *delete-expression*,
71
  - the pointer is used to access a non-static data member or call a
72
  non-static member function of the object, or
73
+ - the pointer is implicitly converted [[conv.ptr]] to a pointer to a
74
  virtual base class, or
75
+ - the pointer is used as the operand of a `static_cast`
76
+ [[expr.static.cast]], except when the conversion is to pointer to
77
  cv `void`, or to pointer to cv `void` and subsequently to pointer to
78
+ cv `char`, cv `unsigned char`, or cv `std::byte` [[cstddef.syn]], or
79
+ - the pointer is used as the operand of a `dynamic_cast`
80
+ [[expr.dynamic.cast]].
 
81
 
82
  [*Example 1*:
83
 
84
  ``` cpp
85
  #include <cstdlib>
 
103
  void* p = std::malloc(sizeof(D1) + sizeof(D2));
104
  B* pb = new (p) D1;
105
  pb->mutate();
106
  *pb; // OK: pb points to valid memory
107
  void* q = pb; // OK: pb points to valid memory
108
+ pb->f(); // undefined behavior: lifetime of *pb has ended
109
  }
110
  ```
111
 
112
  — *end example*]
113
 
 
115
  storage which the object will occupy has been allocated or, after the
116
  lifetime of an object has ended and before the storage which the object
117
  occupied is reused or released, any glvalue that refers to the original
118
  object may be used but only in limited ways. For an object under
119
  construction or destruction, see  [[class.cdtor]]. Otherwise, such a
120
+ glvalue refers to allocated storage [[basic.stc.dynamic.allocation]],
121
+ and using the properties of the glvalue that do not depend on its value
122
+ is well-defined. The program has undefined behavior if:
 
123
 
124
  - the glvalue is used to access the object, or
125
  - the glvalue is used to call a non-static member function of the
126
  object, or
127
+ - the glvalue is bound to a reference to a virtual base class
128
+ [[dcl.init.ref]], or
129
+ - the glvalue is used as the operand of a `dynamic_cast`
130
+ [[expr.dynamic.cast]] or as the operand of `typeid`.
131
 
132
  If, after the lifetime of an object has ended and before the storage
133
  which the object occupied is reused or released, a new object is created
134
  at the storage location which the original object occupied, a pointer
135
  that pointed to the original object, a reference that referred to the
136
  original object, or the name of the original object will automatically
137
  refer to the new object and, once the lifetime of the new object has
138
+ started, can be used to manipulate the new object, if the original
139
+ object is transparently replaceable (see below) by the new object. An
140
+ object o₁ is *transparently replaceable* by an object o₂ if:
141
 
142
+ - the storage that o₂ occupies exactly overlays the storage that o₁
143
+ occupied, and
144
+ - o₁ and o₂ are of the same type (ignoring the top-level cv-qualifiers),
145
+ and
146
+ - o₁ is not a complete const object, and
147
+ - neither o₁ nor o₂ is a potentially-overlapping subobject
148
+ [[intro.object]], and
149
+ - either o₁ and o₂ are both complete objects, or o₁ and o₂ are direct
150
+ subobjects of objects p₁ and p₂, respectively, and p₁ is transparently
151
+ replaceable by p₂.
152
 
153
  [*Example 2*:
154
 
155
  ``` cpp
156
  struct C {
 
174
  c1.f(); // well-defined; c1 refers to a new object of type C
175
  ```
176
 
177
  — *end example*]
178
 
179
+ [*Note 3*: If these conditions are not met, a pointer to the new object
180
  can be obtained from a pointer that represents the address of its
181
+ storage by calling `std::launder` [[ptr.launder]]. — *end note*]
182
 
183
+ If a program ends the lifetime of an object of type `T` with static
184
+ [[basic.stc.static]], thread [[basic.stc.thread]], or automatic
185
+ [[basic.stc.auto]] storage duration and if `T` has a non-trivial
186
+ destructor,[^12] the program must ensure that an object of the original
187
  type occupies that same storage location when the implicit destructor
188
  call takes place; otherwise the behavior of the program is undefined.
189
  This is true even if the block is exited with an exception.
190
 
191
  [*Example 3*:
 
202
  } // undefined behavior at block exit
203
  ```
204
 
205
  — *end example*]
206
 
207
+ Creating a new object within the storage that a const complete object
208
  with static, thread, or automatic storage duration occupies, or within
209
+ the storage that such a const object used to occupy before its lifetime
210
+ ended, results in undefined behavior.
211
 
212
  [*Example 4*:
213
 
214
  ``` cpp
215
  struct B {
 
225
  }
226
  ```
227
 
228
  — *end example*]
229
 
230
+ In this subclause, “before” and “after” refer to the “happens before”
231
+ relation [[intro.multithread]].
232
 
233
+ [*Note 4*: Therefore, undefined behavior results if an object that is
234
  being constructed in one thread is referenced from another thread
235
  without adequate synchronization. — *end note*]
236