@FaulerAffe
-

Как не вызывать деструктор два раза?

Я делаю перегрузку бинарного оператора -. Делаю класс очереди. Делаю выражение c = a - b, где a,b,c – объекты класса очереди. У меня есть функция, которая перегружает этот оператор. Внутри неё создаётся вспомогательный объект, в котором хранится искомая разность. Если я возвращаю этот объект, то у меня после конца функции вызовется его деструктор, очистится память, а результат этого всего запишется в c. Более того, потом ещё вызовется деструктор класса c, и он ещё раз очистит ту же самую память и вылетит ошибка. Как в таких случаях можно поступать? Если использовать this, то у меня изменится объект a, чего происходить не должно. Хотелось бы просто записать результат в c.
class Queue
{
private:
    struct elem
    {
        elem *next, *prev;
        int info;
    };
    elem *head, *tail;
    int len;
public:
    //конструктор
    Queue(double inf)
    {
        head = new elem;
        tail = new elem;
        len = 1;
        head->info = inf;
    };
    
    Queue()
    {
        head = NULL;
        tail = NULL;
        len = 0;
    }
    //деструктор
    ~Queue()
    {
        elem *n = tail;
        while (tail != NULL)
        {
            n = tail;
            tail = tail->next;
            len--;
            delete n;
            n = NULL;
        }
    };
...
};

Queue operator-(Queue a)
    {
        elem* n1 = head;
        Queue answ;
        //создание копии
        for (int i = 0; i < len; i++)
        {
            answ.enqueue(n1->info);
            n1 = n1->prev;
        }

        ...
 
        return answ;
    }
  • Вопрос задан
  • 284 просмотра
Решения вопроса 1
@FaulerAffe Автор вопроса
-
Добавил оператор присваивания, в который передавал тот объект, который затирался. Оказалось, что деструктор этого самого объекта вызывается уже после оператора присваивания, так что я просто записал всё в объект, для которого вызывался оператор присваивания (уже с другими адресами), ну а старый объект уничтожился после этого.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
zagayevskiy
@zagayevskiy
Android developer at Yandex
Проблема здесь не в деструкторе, а в конструкторах. Тебе нужно реализовать конструкторы копирования и перемещения, иначе у тебя так и будут постоянно копироваться указатели из инстанса в инстанс, а при уничтожении будут в итоге такие крещи, как ты описал. Сейчас дефолтный конструктор копирования работает при передаче аргументов и при возврате из функции. Локально это можно полечить ссылками, но глобально – только правильные конструкторы.
Ответ написан
Комментировать
maaGames
@maaGames
Погроммирую программы
В "operator -" нужно передавать константную ссылку, а не по значению.

Вариант 1. Ипользовать конструктор перемещения. 100% гарантии нет, но в ряде случаев копия делаться не будет.

Вариант 2. Вместо оператора использовать функцию, в качестве аргумента принимающую ссылку на результат. Тогда временного объекта вообще не будет, сразу в результирующую очередь будешь данные записывать.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы