Да, вы делаете большую часть времени. [basic.life] p8 говорит:
Если после того, как срок жизни объекта закончился и перед хранилищем, которое объект занят, повторно используется или выпущен, новый объект создается в месте хранения, в котором был загружен исходный объект, указатель, указывающий на исходный объект, ссылка, относящаяся к исходному объекту, или имя исходного объекта будут автоматически ссылаться на новый объект и, если время жизни нового объекта, можно использовать для управления новым объектом, если:
blockquote>
- хранилище для нового объекта точно накладывает место хранения, которое было занято исходным объектом, и
- новый объект имеет тот же тип, что и исходный объект (игнорируя cv-квалификаторы верхнего уровня), а
- тип исходного объекта не является константным, а если тип класса, не содержит какого-либо нестатического элемента данных, тип которого является const-qualit или ссылочным типом, и
- ни исходный объект, ни новый ob ject является потенциально перекрывающимся подобъектом ([intro.object]).
Так что это законно, если у вас нет
const
или ссылочного элемента.Если у вас нет этой гарантии, вам нужно использовать
std::launder
или использовать указатель, возвращенный новым местом размещения (например, вы все равно), если вы хотите использовать новый объект:// no const/ref members anObject->~AnObject(); // destroy object new (anObject) AnObject(); // create new object in same storage, ok anObject->f(); // ok // const/ref members anObject->~AnObject(); auto newObject = new (anObject) AnObject(); anObject->f(); // UB newObject->f(); // ok std::launder(anObject)->f(); // ok