Использование оператора = в сочетании с новым оператором

Мне было интересно, как написать оператор =, чтобы существующая выделенная память для переменной была освобождена.

Например, в приведенном ниже коде при переназначении указателя x x = new ClassExample(4) старая память x->a будет освобождена.

Судя по всему, при использовании new оператор = не применяется (он только для уже существующих значений).

Есть ли способ сделать это (освободить старую память при выделении новой памяти)?

#include <iostream>
#include <cstdlib>

class ClassExample {
public:
    int* a;
    ClassExample& operator= (const ClassExample& rightSide) {
       //..... 
    }

    ClassExample(int val) {
         a = new int(val); 
    }
};

int main()
{
    ClassExample* x = new ClassExample(2);
    x = new ClassExample(4);
    return 0;
}

person Hélène    schedule 03.07.2013    source источник
comment
Ваш оператор присваивания в этом случае не вызывается, потому что вы используете указатели, а не прямые экземпляры. И также помните, что выделенная память никогда не освобождается автоматически, вы должны это сделать. Помогает использование умных указателей.   -  person Some programmer dude    schedule 03.07.2013
comment
На самом деле, в подобном случае почему вы используете указатели? И я имею в виду не только указатели ClassExample в main, но и указатель члена a в классе! Правила, которым вы должны следовать: 1. Не используйте указатели. 2. Если вам нужно использовать указатели, не делайте этого. 3. Если вам все еще приходится использовать указатели, используйте интеллектуальные указатели.   -  person Some programmer dude    schedule 03.07.2013
comment
Подумайте и о безопасности исключений   -  person doctorlove    schedule 03.07.2013


Ответы (2)


Никогда не нарушайте это правило: каждый new должен быть уравновешен delete.

Вы можете использовать интеллектуальный указатель для достижения того, чего хотите, или, в вашем конкретном случае, что-то более простое:

Вкратце, вы создаете класс шаблона WrappedPtr<T> для типа данных T, который содержит указатель T*. В качестве отправной точки вы можете определить оператор присваивания, который удалит текущий обернутый объект, прежде чем принять новый в качестве своих данных-членов. Вам нужно будет позаботиться о создании копии; или даже запретить это.

Настоящий интеллектуальный указатель также каким-то образом реализует подсчет ссылок.

См. http://www.boost.org/doc/libs/1_54_0/libs/smart_ptr/shared_ptr.htm

person Bathsheba    schedule 03.07.2013

Оператор = означает, что вы меняете значение внутри вашего текущего объекта. Здесь вы просто меняете указатель x.

Как вы могли бы это сделать:

ClassExample x(2);
x = ClassExample(4);

Или, в вашем случае, что-то вроде:

ClassExample* x = new ClassExample(2);
*x = *(new ClassExample(4));

Последнее вызовет утечку в вашей программе, поэтому НЕ используйте его. Конечно, вы можете использовать что-то среднее, например:

ClassExample* x = new ClassExample(2);
*x = ClassExample(4);

Этот не протечет.

person Uman    schedule 03.07.2013
comment
Это может не привести к утечке val, но вызов new должен сопровождаться вызовом delete, иначе он будет просачиваться - person doctorlove; 03.07.2013
comment
В моем последнем примере нет проблем, первый ClassExample(2) все еще будет существовать, а ClassExample(4) будет уничтожен после завершения копирования. Тогда, конечно, 'x' придется удалить к концу программы. - person Uman; 05.07.2013