tmp/tmpxc5wnmde/{from.md → to.md}
RENAMED
|
@@ -1,24 +1,24 @@
|
|
| 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 |
-
|
| 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
|
| 17 |
-
[[class.union]]
|
| 18 |
-
[[allocator.members]]. The lifetime of an object
|
| 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]].
|
|
@@ -33,43 +33,44 @@ member subobjects. — *end note*]
|
|
| 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
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
A program may end the lifetime of
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 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[^
|
| 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 |
-
|
| 69 |
-
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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`
|
|
@@ -101,12 +102,12 @@ void B::mutate() {
|
|
| 101 |
|
| 102 |
void g() {
|
| 103 |
void* p = std::malloc(sizeof(D1) + sizeof(D2));
|
| 104 |
B* pb = new (p) D1;
|
| 105 |
pb->mutate();
|
| 106 |
-
*pb; // OK
|
| 107 |
-
void* q = pb; // OK
|
| 108 |
pb->f(); // undefined behavior: lifetime of *pb has ended
|
| 109 |
}
|
| 110 |
```
|
| 111 |
|
| 112 |
— *end example*]
|
|
@@ -141,11 +142,11 @@ 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
|
| 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₂.
|
|
@@ -174,21 +175,23 @@ c1 = c2; // well-defined
|
|
| 174 |
c1.f(); // well-defined; c1 refers to a new object of type C
|
| 175 |
```
|
| 176 |
|
| 177 |
— *end example*]
|
| 178 |
|
| 179 |
-
[*Note
|
| 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,[^
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
|
|
|
|
|
|
| 190 |
|
| 191 |
[*Example 3*:
|
| 192 |
|
| 193 |
``` cpp
|
| 194 |
class T { };
|
|
@@ -202,11 +205,11 @@ void h() {
|
|
| 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*:
|
|
@@ -228,9 +231,9 @@ void h() {
|
|
| 228 |
— *end example*]
|
| 229 |
|
| 230 |
In this subclause, “before” and “after” refer to the “happens before”
|
| 231 |
relation [[intro.multithread]].
|
| 232 |
|
| 233 |
-
[*Note
|
| 234 |
being constructed in one thread is referenced from another thread
|
| 235 |
without adequate synchronization. — *end note*]
|
| 236 |
|
|
|
|
| 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]],
|
| 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]], [[class.copy.ctor]], and [[class.copy.assign]], and
|
| 18 |
+
except as described in [[allocator.members]]. The lifetime of an object
|
| 19 |
+
*o* of type `T` ends 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]].
|
|
|
|
| 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 can differ from the behavior of an object whose lifetime has
|
| 41 |
+
started and not ended. [[class.base.init]] and [[class.cdtor]] describe
|
| 42 |
+
the behavior of an object during its periods of construction and
|
| 43 |
+
destruction. — *end note*]
|
| 44 |
+
|
| 45 |
+
A program may end the lifetime of an object of class type without
|
| 46 |
+
invoking the destructor, by reusing or releasing the storage as
|
| 47 |
+
described above.
|
| 48 |
+
|
| 49 |
+
[*Note 3*: A *delete-expression* [[expr.delete]] invokes the destructor
|
| 50 |
+
prior to releasing the storage. — *end note*]
|
| 51 |
+
|
| 52 |
+
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
|
| 75 |
virtual base class, or
|
| 76 |
- the pointer is used as the operand of a `static_cast`
|
|
|
|
| 102 |
|
| 103 |
void g() {
|
| 104 |
void* p = std::malloc(sizeof(D1) + sizeof(D2));
|
| 105 |
B* pb = new (p) D1;
|
| 106 |
pb->mutate();
|
| 107 |
+
*pb; // OK, pb points to valid memory
|
| 108 |
+
void* q = pb; // OK, pb points to valid memory
|
| 109 |
pb->f(); // undefined behavior: lifetime of *pb has ended
|
| 110 |
}
|
| 111 |
```
|
| 112 |
|
| 113 |
— *end example*]
|
|
|
|
| 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
|
| 147 |
+
- o₁ is not a const, complete object, and
|
| 148 |
- neither o₁ nor o₂ is a potentially-overlapping subobject
|
| 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₂.
|
|
|
|
| 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 { };
|
|
|
|
| 205 |
} // undefined behavior at block exit
|
| 206 |
```
|
| 207 |
|
| 208 |
— *end example*]
|
| 209 |
|
| 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*:
|
|
|
|
| 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 |
|