From Jason Turner

[class.cdtor]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpjb4598ti/{from.md → to.md} +71 -37
tmp/tmpjb4598ti/{from.md → to.md} RENAMED
@@ -1,6 +1,6 @@
1
- ## Construction and destruction <a id="class.cdtor">[[class.cdtor]]</a>
2
 
3
  For an object with a non-trivial constructor, referring to any
4
  non-static member or base class of the object before the constructor
5
  begins execution results in undefined behavior. For an object with a
6
  non-trivial destructor, referring to any non-static member or base class
@@ -15,14 +15,14 @@ struct Y : X { Y(); }; // non-trivial
15
  struct A { int a; };
16
  struct B : public A { int j; Y y; }; // non-trivial
17
 
18
  extern B bobj;
19
  B* pb = &bobj; // OK
20
- int* p1 = &bobj.a; // undefined, refers to base class member
21
- int* p2 = &bobj.y.i; // undefined, refers to member's member
22
 
23
- A* pa = &bobj; // undefined, upcast to a base class type
24
  B bobj; // definition of bobj
25
 
26
  extern X xobj;
27
  int* p3 = &xobj.i; // OK, X is a trivial class
28
  X xobj;
@@ -41,10 +41,45 @@ struct Y {
41
  };
42
  ```
43
 
44
  — *end example*]
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  To explicitly or implicitly convert a pointer (a glvalue) referring to
47
  an object of class `X` to a pointer (reference) to a direct or indirect
48
  base class `B` of `X`, the construction of `X` and the construction of
49
  all of its direct or indirect bases that directly or indirectly derive
50
  from `B` shall have started and the destruction of these classes shall
@@ -53,21 +88,21 @@ behavior. To form a pointer to (or access the value of) a direct
53
  non-static member of an object `obj`, the construction of `obj` shall
54
  have started and its destruction shall not have completed, otherwise the
55
  computation of the pointer value (or accessing the member value) results
56
  in undefined behavior.
57
 
58
- [*Example 2*:
59
 
60
  ``` cpp
61
  struct A { };
62
  struct B : virtual A { };
63
  struct C : B { };
64
  struct D : virtual A { D(A*); };
65
  struct X { X(A*); };
66
 
67
  struct E : C, D, X {
68
- E() : D(this), // undefined: upcast from E* to A* might use path E* → D* → A*
69
  // but D is not constructed
70
 
71
  // ``D((C*)this)'' would be defined: E* → C* is defined because E() has started,
72
  // and C* → A* is defined because C is fully constructed
73
 
@@ -75,24 +110,24 @@ struct E : C, D, X {
75
  };
76
  ```
77
 
78
  — *end example*]
79
 
80
- Member functions, including virtual functions ([[class.virtual]]), can
81
- be called during construction or destruction ([[class.base.init]]).
82
- When a virtual function is called directly or indirectly from a
83
- constructor or from a destructor, including during the construction or
84
- destruction of the class’s non-static data members, and the object to
85
- which the call applies is the object (call it `x`) under construction or
86
- destruction, the function called is the final overrider in the
87
- constructor’s or destructor’s class and not one overriding it in a
88
- more-derived class. If the virtual function call uses an explicit class
89
- member access ([[expr.ref]]) and the object expression refers to the
90
- complete object of `x` or one of that object’s base class subobjects but
91
- not `x` or one of its base class subobjects, the behavior is undefined.
92
 
93
- [*Example 3*:
94
 
95
  ``` cpp
96
  struct V {
97
  virtual void f();
98
  virtual void g();
@@ -115,43 +150,42 @@ struct D : A, B {
115
 
116
  B::B(V* v, A* a) {
117
  f(); // calls V::f, not A::f
118
  g(); // calls B::g, not D::g
119
  v->g(); // v is base of B, the call is well-defined, calls B::g
120
- a->f(); // undefined behavior, a's type not a base of B
121
  }
122
  ```
123
 
124
  — *end example*]
125
 
126
- The `typeid` operator ([[expr.typeid]]) can be used during construction
127
- or destruction ([[class.base.init]]). When `typeid` is used in a
 
 
 
 
 
 
 
 
 
 
 
 
128
  constructor (including the *mem-initializer* or default member
129
- initializer ([[class.mem]]) for a non-static data member) or in a
130
- destructor, or used in a function called (directly or indirectly) from a
131
- constructor or destructor, if the operand of `typeid` refers to the
132
- object under construction or destruction, `typeid` yields the
133
- `std::type_info` object representing the constructor or destructor’s
134
- class. If the operand of `typeid` refers to the object under
135
- construction or destruction and the static type of the operand is
136
- neither the constructor or destructor’s class nor one of its bases, the
137
- behavior is undefined.
138
-
139
- `dynamic_cast`s ([[expr.dynamic.cast]]) can be used during construction
140
- or destruction ([[class.base.init]]). When a `dynamic_cast` is used in
141
- a constructor (including the *mem-initializer* or default member
142
  initializer for a non-static data member) or in a destructor, or used in
143
  a function called (directly or indirectly) from a constructor or
144
  destructor, if the operand of the `dynamic_cast` refers to the object
145
  under construction or destruction, this object is considered to be a
146
  most derived object that has the type of the constructor or destructor’s
147
  class. If the operand of the `dynamic_cast` refers to the object under
148
  construction or destruction and the static type of the operand is not a
149
  pointer to or object of the constructor or destructor’s own class or one
150
  of its bases, the `dynamic_cast` results in undefined behavior.
151
 
152
- [*Example 4*:
153
 
154
  ``` cpp
155
  struct V {
156
  virtual void f();
157
  };
@@ -169,11 +203,11 @@ struct D : A, B {
169
  B::B(V* v, A* a) {
170
  typeid(*this); // type_info for B
171
  typeid(*v); // well-defined: *v has type V, a base of B yields type_info for B
172
  typeid(*a); // undefined behavior: type A not a base of B
173
  dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B results in B*
174
- dynamic_cast<B*>(a); // undefined behavior, a has type A*, A not a base of B
175
  }
176
  ```
177
 
178
  — *end example*]
179
 
 
1
+ ### Construction and destruction <a id="class.cdtor">[[class.cdtor]]</a>
2
 
3
  For an object with a non-trivial constructor, referring to any
4
  non-static member or base class of the object before the constructor
5
  begins execution results in undefined behavior. For an object with a
6
  non-trivial destructor, referring to any non-static member or base class
 
15
  struct A { int a; };
16
  struct B : public A { int j; Y y; }; // non-trivial
17
 
18
  extern B bobj;
19
  B* pb = &bobj; // OK
20
+ int* p1 = &bobj.a; // undefined behavior: refers to base class member
21
+ int* p2 = &bobj.y.i; // undefined behavior: refers to member's member
22
 
23
+ A* pa = &bobj; // undefined behavior: upcast to a base class type
24
  B bobj; // definition of bobj
25
 
26
  extern X xobj;
27
  int* p3 = &xobj.i; // OK, X is a trivial class
28
  X xobj;
 
41
  };
42
  ```
43
 
44
  — *end example*]
45
 
46
+ During the construction of an object, if the value of the object or any
47
+ of its subobjects is accessed through a glvalue that is not obtained,
48
+ directly or indirectly, from the constructor’s `this` pointer, the value
49
+ of the object or subobject thus obtained is unspecified.
50
+
51
+ [*Example 2*:
52
+
53
+ ``` cpp
54
+ struct C;
55
+ void no_opt(C*);
56
+
57
+ struct C {
58
+ int c;
59
+ C() : c(0) { no_opt(this); }
60
+ };
61
+
62
+ const C cobj;
63
+
64
+ void no_opt(C* cptr) {
65
+ int i = cobj.c * 100; // value of cobj.c is unspecified
66
+ cptr->c = 1;
67
+ cout << cobj.c * 100 // value of cobj.c is unspecified
68
+ << '\n';
69
+ }
70
+
71
+ extern struct D d;
72
+ struct D {
73
+ D(int a) : a(a), b(d.a) {}
74
+ int a, b;
75
+ };
76
+ D d = D(1); // value of d.b is unspecified
77
+ ```
78
+
79
+ — *end example*]
80
+
81
  To explicitly or implicitly convert a pointer (a glvalue) referring to
82
  an object of class `X` to a pointer (reference) to a direct or indirect
83
  base class `B` of `X`, the construction of `X` and the construction of
84
  all of its direct or indirect bases that directly or indirectly derive
85
  from `B` shall have started and the destruction of these classes shall
 
88
  non-static member of an object `obj`, the construction of `obj` shall
89
  have started and its destruction shall not have completed, otherwise the
90
  computation of the pointer value (or accessing the member value) results
91
  in undefined behavior.
92
 
93
+ [*Example 3*:
94
 
95
  ``` cpp
96
  struct A { };
97
  struct B : virtual A { };
98
  struct C : B { };
99
  struct D : virtual A { D(A*); };
100
  struct X { X(A*); };
101
 
102
  struct E : C, D, X {
103
+ E() : D(this), // undefined behavior: upcast from E* to A* might use path E* → D* → A*
104
  // but D is not constructed
105
 
106
  // ``D((C*)this)'' would be defined: E* → C* is defined because E() has started,
107
  // and C* → A* is defined because C is fully constructed
108
 
 
110
  };
111
  ```
112
 
113
  — *end example*]
114
 
115
+ Member functions, including virtual functions [[class.virtual]], can be
116
+ called during construction or destruction [[class.base.init]]. When a
117
+ virtual function is called directly or indirectly from a constructor or
118
+ from a destructor, including during the construction or destruction of
119
+ the class’s non-static data members, and the object to which the call
120
+ applies is the object (call it `x`) under construction or destruction,
121
+ the function called is the final overrider in the constructor’s or
122
+ destructor’s class and not one overriding it in a more-derived class. If
123
+ the virtual function call uses an explicit class member access
124
+ [[expr.ref]] and the object expression refers to the complete object of
125
+ `x` or one of that object’s base class subobjects but not `x` or one of
126
+ its base class subobjects, the behavior is undefined.
127
 
128
+ [*Example 4*:
129
 
130
  ``` cpp
131
  struct V {
132
  virtual void f();
133
  virtual void g();
 
150
 
151
  B::B(V* v, A* a) {
152
  f(); // calls V::f, not A::f
153
  g(); // calls B::g, not D::g
154
  v->g(); // v is base of B, the call is well-defined, calls B::g
155
+ a->f(); // undefined behavior: a's type not a base of B
156
  }
157
  ```
158
 
159
  — *end example*]
160
 
161
+ The `typeid` operator [[expr.typeid]] can be used during construction or
162
+ destruction [[class.base.init]]. When `typeid` is used in a constructor
163
+ (including the *mem-initializer* or default member initializer
164
+ [[class.mem]] for a non-static data member) or in a destructor, or used
165
+ in a function called (directly or indirectly) from a constructor or
166
+ destructor, if the operand of `typeid` refers to the object under
167
+ construction or destruction, `typeid` yields the `std::type_info` object
168
+ representing the constructor or destructor’s class. If the operand of
169
+ `typeid` refers to the object under construction or destruction and the
170
+ static type of the operand is neither the constructor or destructor’s
171
+ class nor one of its bases, the behavior is undefined.
172
+
173
+ `dynamic_cast`s [[expr.dynamic.cast]] can be used during construction or
174
+ destruction [[class.base.init]]. When a `dynamic_cast` is used in a
175
  constructor (including the *mem-initializer* or default member
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  initializer for a non-static data member) or in a destructor, or used in
177
  a function called (directly or indirectly) from a constructor or
178
  destructor, if the operand of the `dynamic_cast` refers to the object
179
  under construction or destruction, this object is considered to be a
180
  most derived object that has the type of the constructor or destructor’s
181
  class. If the operand of the `dynamic_cast` refers to the object under
182
  construction or destruction and the static type of the operand is not a
183
  pointer to or object of the constructor or destructor’s own class or one
184
  of its bases, the `dynamic_cast` results in undefined behavior.
185
 
186
+ [*Example 5*:
187
 
188
  ``` cpp
189
  struct V {
190
  virtual void f();
191
  };
 
203
  B::B(V* v, A* a) {
204
  typeid(*this); // type_info for B
205
  typeid(*v); // well-defined: *v has type V, a base of B yields type_info for B
206
  typeid(*a); // undefined behavior: type A not a base of B
207
  dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B results in B*
208
+ dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of B
209
  }
210
  ```
211
 
212
  — *end example*]
213