Помогите разобраться
От: -newbie-  
Дата: 19.08.03 07:51
Оценка: :)
При вызове "aaa.NewX(77)" (см. ниже) для temp деструктор почему-то вызывается дважды в результате программа выдаёт ошибку когда пытается второй раз удалить *X.
Может кто подскажет как написать это правильно. (компилировалось на MS VC++ v7)

class A
{
public:
A() { X = new int; }
~A(){ delete X; }
A NewA(int a);
int *X;
};

A A::NewA(int a)
{
A temp;
*(temp.X) = a;
return temp;
}

main()
{
A aaa;
aaa.NewA(77);
}
Re: Помогите разобраться
От: Lorenzo_LAMAS  
Дата: 19.08.03 07:58
Оценка:
Раз у тебя есть какой-то нетривиальный деструктор, который вызывает delete, то определи конструктор копий и оператор копирующего присваивания

A(const A &)
A &operator = (const A &);

А зачем вообще тебе такая кривизна?
Of course, the code must be complete enough to compile and link.
Re: Помогите разобраться
От: Анатолий Широков СССР  
Дата: 19.08.03 08:11
Оценка: 2 (1)
Чтобы решить проблему, тебе нужен свой собственный конструктор копирования и оператор присваивания, потому что компилятору невдомек, что ты вкладываешь другой смысл в копирование указателей:

class A
{
public:
...
   A(const A &a) : X(a.X ? new int(*(a.X)) : 0)
   {
   }
   A& operator = (const A &a)
   {
      A(a).swap(*this);
      return *this;
   }
   void swap(A &a)
   {
      std::swap(X, a.X);
   }
...
};
Re: Помогите разобраться
От: Vamp Россия  
Дата: 19.08.03 08:19
Оценка:
N>class A
N>{
N>public:
N>    A() { X = new int; }
N>    ~A(){ delete X; }
N>    A NewA(int a);
N>    int *X;
N>};

N>A A::NewA(int a)
N>{
N>    A temp;
N>    *(temp.X) = a;
N>    return temp; /*Вот здесь выполняется почленное копирование, после чего 
                       вызывается деструктор для temp. *X удаляется */   
N>}

N>main()
N>{
N>A aaa;
N>aaa.NewA(77); /*А здесь деструктор вызывается для удаления временного объекта,
                при этом *X указывает на удаленный объект*/
N>}


Вообще если в классе есть указатели, надо переопределять оператор присваивания и копирующий конструктор.
Да здравствует мыло душистое и веревка пушистая.
Re: Помогите разобраться
От: -newbie-  
Дата: 19.08.03 08:22
Оценка: :)
Большое спасибо.
Не знал, если честно, насчёт конструктора копий.
Как говорится: век живи — век учись.
Re: Помогите разобраться
От: DanilB Россия  
Дата: 20.08.03 04:06
Оценка: :)
Здравствуйте, -newbie-, Вы писали:

N>При вызове "aaa.NewX(77)" (см. ниже) для temp деструктор почему-то вызывается дважды в результате программа выдаёт ошибку когда пытается второй раз удалить *X.

N>Может кто подскажет как написать это правильно. (компилировалось на MS VC++ v7)

N>class A

N>{
N>public:
N> A() { X = new int; }
N> ~A(){ delete X; }
N> A NewA(int a);
N> int *X;
N>};

N>A A::NewA(int a)

N>{
N> A temp;
N> *(temp.X) = a;
N> return temp;
N>}

N>main()

N>{
N>A aaa;
N>aaa.NewA(77);
N>}

Попробуй в деструкторе
~A(){if(X) {delete X; X = NULL;} }
Re[2]: Помогите разобраться
От: Вадим Никулин Россия Здесь
Дата: 20.08.03 05:26
Оценка:
Здравствуйте, DanilB, Вы писали:

DB>Попробуй в деструкторе

DB>~A(){if(X) {delete X; X = NULL;} }

А Вы, батенька, шутник! Сначала попробуйте то, что Вы предложили.
Re[2]: Помогите разобраться
От: -newbie-  
Дата: 20.08.03 06:45
Оценка:
Здравствуйте, DanilB, Вы писали:

DB>Попробуй в деструкторе

DB>~A(){if(X) {delete X; X = NULL;} }

Ну это не поможет.
Как я понял из выше сказанного, в "return temp" передаётся не сам temp а его копия.
И т.к. компилятор "не знает" как копировать память на которую ссылается *X, то нужно определить контсруктор копирования A(const A &a), где а — объект который копируется.

Так что, деструктор вызывается по одному разу для двух разных объектов. Один раз для temp в строке "return temp". И второй раз для его копии в aaa.NewA(77);
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.