From Jason Turner

[basic.life]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp1nefo2f4/{from.md → to.md} +80 -44
tmp/tmp1nefo2f4/{from.md → to.md} RENAMED
@@ -1,40 +1,51 @@
1
  ## Object lifetime <a id="basic.life">[[basic.life]]</a>
2
 
3
- The *lifetime* of an object is a runtime property of the object. An
4
- object is said to have non-trivial initialization if it is of a class or
5
- aggregate type and it or one of its members is initialized by a
6
- constructor other than a trivial default constructor. initialization by
7
- a trivial copy/move constructor is non-trivial initialization. The
8
- lifetime of an object of type `T` begins when:
 
 
 
 
9
 
10
  - storage with the proper alignment and size for type `T` is obtained,
11
  and
12
- - if the object has non-trivial initialization, its initialization is
13
- complete.
14
 
15
- The lifetime of an object of type `T` ends when:
 
 
 
16
 
17
  - if `T` is a class type with a non-trivial destructor (
18
  [[class.dtor]]), the destructor call starts, or
19
- - the storage which the object occupies is reused or released.
20
-
21
- The lifetime of an array object starts as soon as storage with proper
22
- size and alignment is obtained, and its lifetime ends when the storage
23
- which the array occupies is reused or released. [[class.base.init]]
24
- describes the lifetime of base and member subobjects.
25
-
26
- The properties ascribed to objects throughout this International
27
- Standard apply for a given object only during its lifetime. In
28
- particular, before the lifetime of an object starts and after its
29
- lifetime ends there are significant restrictions on the use of the
30
- object, as described below, in  [[class.base.init]] and in 
 
 
 
 
31
  [[class.cdtor]]. Also, the behavior of an object under construction and
32
  destruction might not be the same as the behavior of an object whose
33
  lifetime has started and not ended. [[class.base.init]] and 
34
  [[class.cdtor]] describe the behavior of objects during the construction
35
- and destruction phases.
36
 
37
  A program may end the lifetime of any object by reusing the storage
38
  which the object occupies or by explicitly calling the destructor for an
39
  object of a class type with a non-trivial destructor. For an object of a
40
  class type with a non-trivial destructor, the program is not required to
@@ -46,32 +57,37 @@ called and any program that depends on the side effects produced by the
46
  destructor has undefined behavior.
47
 
48
  Before the lifetime of an object has started but after the storage which
49
  the object will occupy has been allocated[^16] or, after the lifetime of
50
  an object has ended and before the storage which the object occupied is
51
- reused or released, any pointer that refers to the storage location
52
- where the object will be or was located may be used but only in limited
53
- ways. For an object under construction or destruction, see 
54
- [[class.cdtor]]. Otherwise, such a pointer refers to allocated storage (
55
- [[basic.stc.dynamic.deallocation]]), and using the pointer as if the
56
- pointer were of type `void*`, is well-defined. Indirection through such
57
- a pointer is permitted but the resulting lvalue may only be used in
58
- limited ways, as described below. The program has undefined behavior if:
 
59
 
60
  - the object will be or was of a class type with a non-trivial
61
  destructor and the pointer is used as the operand of a
62
  *delete-expression*,
63
  - the pointer is used to access a non-static data member or call a
64
  non-static member function of the object, or
65
  - the pointer is implicitly converted ([[conv.ptr]]) to a pointer to a
66
  virtual base class, or
67
  - the pointer is used as the operand of a `static_cast` (
68
  [[expr.static.cast]]), except when the conversion is to pointer to
69
- *cv* `void`, or to pointer to *cv* `void` and subsequently to pointer
70
- to either *cv* `char` or *cv* `unsigned char`, or
 
71
  - the pointer is used as the operand of a `dynamic_cast` (
72
  [[expr.dynamic.cast]]).
 
 
 
73
  ``` cpp
74
  #include <cstdlib>
75
 
76
  struct B {
77
  virtual void f();
@@ -90,16 +106,18 @@ limited ways, as described below. The program has undefined behavior if:
90
 
91
  void g() {
92
  void* p = std::malloc(sizeof(D1) + sizeof(D2));
93
  B* pb = new (p) D1;
94
  pb->mutate();
95
- &pb; // OK: pb points to valid memory
96
  void* q = pb; // OK: pb points to valid memory
97
  pb->f(); // undefined behavior, lifetime of *pb has ended
98
  }
99
  ```
100
 
 
 
101
  Similarly, before the lifetime of an object has started but after the
102
  storage which the object will occupy has been allocated or, after the
103
  lifetime of an object has ended and before the storage which the object
104
  occupied is reused or released, any glvalue that refers to the original
105
  object may be used but only in limited ways. For an object under
@@ -107,14 +125,13 @@ construction or destruction, see  [[class.cdtor]]. Otherwise, such a
107
  glvalue refers to allocated storage (
108
  [[basic.stc.dynamic.deallocation]]), and using the properties of the
109
  glvalue that do not depend on its value is well-defined. The program has
110
  undefined behavior if:
111
 
112
- - an lvalue-to-rvalue conversion ([[conv.lval]]) is applied to such a
113
- glvalue,
114
- - the glvalue is used to access a non-static data member or call a
115
- non-static member function of the object, or
116
  - the glvalue is bound to a reference to a virtual base class (
117
  [[dcl.init.ref]]), or
118
  - the glvalue is used as the operand of a `dynamic_cast` (
119
  [[expr.dynamic.cast]]) or as the operand of `typeid`.
120
 
@@ -134,10 +151,13 @@ started, can be used to manipulate the new object, if:
134
  class type, does not contain any non-static data member whose type is
135
  const-qualified or a reference type, and
136
  - the original object was a most derived object ([[intro.object]]) of
137
  type `T` and the new object is a most derived object of type `T` (that
138
  is, they are not base class subobjects).
 
 
 
139
  ``` cpp
140
  struct C {
141
  int i;
142
  void f();
143
  const C& operator=( const C& );
@@ -156,18 +176,26 @@ started, can be used to manipulate the new object, if:
156
  C c2;
157
  c1 = c2; // well-defined
158
  c1.f(); // well-defined; c1 refers to a new object of type C
159
  ```
160
 
 
 
 
 
 
 
161
  If a program ends the lifetime of an object of type `T` with static (
162
  [[basic.stc.static]]), thread ([[basic.stc.thread]]), or automatic (
163
  [[basic.stc.auto]]) storage duration and if `T` has a non-trivial
164
  destructor,[^17] the program must ensure that an object of the original
165
  type occupies that same storage location when the implicit destructor
166
  call takes place; otherwise the behavior of the program is undefined.
167
  This is true even if the block is exited with an exception.
168
 
 
 
169
  ``` cpp
170
  class T { };
171
  struct B {
172
  ~B();
173
  };
@@ -176,14 +204,18 @@ void h() {
176
  B b;
177
  new (&b) T;
178
  } // undefined behavior at block exit
179
  ```
180
 
181
- Creating a new object at the storage location that a `const` object with
182
- static, thread, or automatic storage duration occupies or, at the
183
- storage location that such a `const` object used to occupy before its
184
- lifetime ended results in undefined behavior.
 
 
 
 
185
 
186
  ``` cpp
187
  struct B {
188
  B();
189
  ~B();
@@ -195,10 +227,14 @@ void h() {
195
  b.~B();
196
  new (const_cast<B*>(&b)) const B; // undefined behavior
197
  }
198
  ```
199
 
 
 
200
  In this section, “before” and “after” refer to the “happens before”
201
- relation ([[intro.multithread]]). Therefore, undefined behavior results
202
- if an object that is being constructed in one thread is referenced from
203
- another thread without adequate synchronization.
 
 
204
 
 
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
 
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>
91
 
92
  struct B {
93
  virtual void f();
 
106
 
107
  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
+
119
  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
 
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
 
 
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 {
161
  int i;
162
  void f();
163
  const C& operator=( const C& );
 
176
  C c2;
177
  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*:
196
+
197
  ``` cpp
198
  class T { };
199
  struct B {
200
  ~B();
201
  };
 
204
  B b;
205
  new (&b) T;
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 {
220
  B();
221
  ~B();
 
227
  b.~B();
228
  new (const_cast<B*>(&b)) const B; // undefined behavior
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