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
|
| 6 |
-
|
| 7 |
-
constructor
|
|
|
|
|
|
|
| 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[^
|
| 59 |
|
| 60 |
-
or
|
| 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
|
| 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
|
| 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 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 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,[^
|
| 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
|
| 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
|
| 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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|