What will be a safe way to access A in the destructor of B? (since we may also be in the destructor of A).
There isn't safe way:
3.8/1
[...]The lifetime of an object of type T ends when:
— if T is a class type with a non-trivial destructor (12.4), the destructor call starts [...]
I think it's straightforward that you can't access object after it's lifetime has ended.
EDIT: As Chris Drew wrote in comment you can use object after it's destructor started, sorry, my mistake I missed out one important sentence in the standard:
3.8/5
Before the lifetime of an object has started but after the storage which the object will occupy has been
allocated or, after the lifetime of an object has ended and before the storage which the object occupied is
reused or released, any pointer that refers to the storage location where the object will be or was located
may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise,
such a pointer refers to allocated storage (3.7.4.2), and using the pointer as if the pointer were of type void*,
is well-defined. Such a pointer may be dereferenced but the resulting lvalue may only be used in limited
ways, as described below. The program has undefined behavior if:
[...]
In 12.7 there is list of things you can do during construction and destruction, some of the most important:
12.7/3:
To explicitly or implicitly convert a pointer (a glvalue) referring to an object of class X to a pointer (reference)
to a direct or indirect base class B of X, the construction of X and the construction of all of its direct or
indirect bases that directly or indirectly derive from B shall have started and the destruction of these classes shall not have completed, otherwise the conversion results in undefined behavior. To form a pointer to (or
access the value of) a direct non-static member of an object obj, the construction of obj shall have started
and its destruction shall not have completed, otherwise the computation of the pointer value (or accessing
the member value) results in undefined behavior.
12.7/4
Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2).
When a virtual function is called directly or indirectly from a constructor or from a destructor, including
during the construction or destruction of the class’s non-static data members, and the object to which the
call applies is the object (call it x) under construction or destruction, the function called is the final overrider
in the constructor’s or destructor’s class and not one overriding it in a more-derived class. If the virtual
function call uses an explicit class member access (5.2.5) and the object expression refers to the complete
object of x or one of that object’s base class subobjects but not x or one of its base class subobjects, the
behavior is undefined.
shared_ptr
won't help, it's destructor will be still invoked 2 times:A destructor
->B destructor
->shared_ptr(to A) destructor
->A destructor
->B destructor
->shared_ptr destructor
= double destructor = Undefined Behaviour, didn't you meanweak_ptr
– BruneiC
fromA
containing the parts thatB
has a dependency on? ThenA
can ensure thatB
is destroyed beforeC
and thatB
can't access any parts ofA
that it shouldn't like this. – Vermont