Оба случая в ответе выше приводят к UB. В общем, идиомы следует избегать, потому что есть так много разных способов, которые могут привести к UB.
т мой вопрос@DeadMG говорит, что реинициализация класса через указатель является неопределенным поведением. Есть ли где-нибудь упоминание об этом в стандарте?this
Пример:
Пример вывода на Ideone
#include <iostream>
class X{
int _i;
public:
X() : _i(0) { std::cout << "X()\n"; }
X(int i) : _i(i) { std::cout << "X(int)\n"; }
~X(){ std::cout << "~X()\n"; }
void foo(){
this->~X();
new (this) X(5);
}
void print_i(){
std::cout << _i << "\n";
}
};
int main(){
X x;
x.foo();
// mock random stack noise
int noise[20];
x.print_i();
}
(Я знаю, что UB также может быть «на первый взгляд правильным поведением»).Обратите внимание, что я не вызывал деструктор вне класса, чтобы не получить доступ к объекту, время жизни которого закончилось. Также обратите внимание, что @DeadMG говорит, что прямой вызов деструктора в порядке, если он вызывается один раз для каждого конструктора.
Эта структура (вызывающая деструктор, а затем конструктор с размещением new) была довольно популярным способом реализации оператора присваивания, пока исключение не оказалось небезопасным. Я не помню, чтобы кто-нибудь говорил, что это был UB в отсутствие исключения. Вероятно, есть случаи с виртуальными функциями и множественным наследованием, которые являются UB.