Re[3]: Безопасно ли присваивать один указатель другому?..
От: Croessmah  
Дата: 23.03.18 17:27
Оценка: 37 (4) +2
Здравствуйте, okman, Вы писали:
O>Хотелось бы понять, насколько такое поведение (т.е. разыменование указателя, возможно висячего,
O>при выполнении приведений типов по иерархии наследования) легально с точки зрения стандарта C++.
O>Или же это сугубо implementation-defined?..


Если я правильно понял, то Вы наткнулись на неопределенное поведение при преобразовании указателей:


С++14
12.7 Construction and destruction

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.
[Example:

struct A { };
struct B : virtual A { };
struct C : B { };
struct D : virtual A { D(A*); };
struct X { X(A*); };



struct E : C, D, X { //undefined: upcast from E* to A*
    E() : D(this),   //might use path E* → D* → A*
                     // but D is not constructed
                     // D((C*)this), // defined:
                     // E* → C* defined because E() has started
                     // and C* → A* defined because
                     // C fully constructed
    X(this) {        // defined: upon construction of X,      
    }                // C/B/D/A sublattice is fully constructed            
};
— end example ]


То есть для Вашего случая сначала необходимо сделать преобразование (присваивание) пока объект не уничтожен, и только затем удалять объект:

    Base * p2;
    p2 = p1;
    delete p1;
    printf("p2 = %p\r\n", (void *)p2);//Ok
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.