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
|
| 4 |
-
object is said to have non-
|
| 5 |
-
aggregate type and it or one of
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
- storage with the proper alignment and size for type `T` is obtained,
|
| 11 |
and
|
| 12 |
-
- if the object has non-
|
| 13 |
-
complete
|
| 14 |
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
| 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
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 52 |
-
where the object will be or was located may be used but
|
| 53 |
-
ways. For an object under construction or destruction,
|
| 54 |
-
[[class.cdtor]]. Otherwise, such a pointer refers to allocated
|
| 55 |
-
[[basic.stc.dynamic.deallocation]]), and using the pointer as
|
| 56 |
-
pointer were of type `void*`, is well-defined. Indirection
|
| 57 |
-
a pointer is permitted but the resulting lvalue may only be
|
| 58 |
-
limited ways, as described below. The program has undefined
|
|
|
|
| 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 |
-
|
| 70 |
-
|
|
|
|
| 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 |
-
|
| 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 |
-
-
|
| 113 |
-
|
| 114 |
-
|
| 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 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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]]).
|
| 202 |
-
|
| 203 |
-
|
|
|
|
|
|
|
| 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 |
|