Как не вызывать деструктор два раза?
Проблема здесь не в деструкторе, а в конструкторах. Тебе нужно реализовать конструкторы копирования и перемещения, иначе у тебя так и будут постоянно копироваться указатели из инстанса в инстанс, а при уничтожении будут в итоге такие крещи, как ты описал. Сейчас дефолтный конструктор копирования работает при передаче аргументов и при возврате из функции.  Локально это можно полечить ссылками, но глобально – только правильные конструкторы.
Добавил оператор присваивания, в который передавал тот объект, который затирался. Оказалось, что деструктор этого самого объекта вызывается уже после оператора присваивания, так что я просто записал всё в объект, для которого вызывался оператор присваивания (уже с другими адресами), ну а старый объект уничтожился после этого.