Операторы в C++
От: Vigen  
Дата: 20.01.03 15:30
Оценка: 2 (1)
Привет всем!!!
Заранее благодарю за чтение сообщения и ответ!
Меня шокировало то, что я узнал продеббагив в ассемблерном коде прожку (пишу м MS VC++ .NET)...

Есть класс mpint (multi precision integer). Соответственно имплементированны операторы суммы, вычитания, умножения и т.д.. Память для хранения данных резервируется в классе динамически. И тут-то номер! Вызывая оператор сложения получаем ошибку с памятью. Пример:


mpint a("123"), b("1AF"), c;
c=a+b;  //не работает

//Из класса mpint...
mpint::operator+(mpint &val)
{
   mpint tmp(this);
   //здесь код сложения
   return tmp;
}


Ошибка в том, что до того как вернуть 'tmp' в виде суммы 'a' и 'b', вызывается деструктор 'tmp', который уничтожает результат суммы.
Пробуя статическое выделение памяти для хранения данных класса, ошибок с памятью нет, но это лишь кажущаяся "правильность": деструктор 'tmp' все равно вызывается. Просто эта память, выделенная изначально под 'tmp', "никто" не перезаписывает --> правильность лишь кажется...

Пожалуйста, объясните мне смысл операторов +, -, / и т.д., если всегда вызывается деструктор!!! Или может я вообще ничего не понимаю....
Большое спасибо!!!
Виген
Re: Операторы в C++
От: Павел Кузнецов  
Дата: 20.01.03 15:33
Оценка:
Здравствуйте, Vigen, Вы писали:

V><...>


V>Ошибка в том, что до того как вернуть 'tmp' в виде суммы 'a' и 'b', вызывается деструктор 'tmp', который уничтожает результат суммы.


Приведи, пожалуйста минимальный компилируемый код, на котором воспроизводится ошибка.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: Операторы в C++
От: Slamin США  
Дата: 20.01.03 15:35
Оценка:
Здравствуйте, Vigen, Вы писали:

V>

V>mpint a("123"), b("1AF"), c;
V>c=a+b;  //не работает

V>//Из класса mpint...
V>mpint::operator+(mpint &val)
V>{
V>   mpint tmp(this);
V>   //здесь код сложения
V>   return tmp;
V>}
V>


Скорее всего оператор определен как
mpint& mpint::operator+(mpint &val)

Нужно:
mpint mpint::operator+(mpint &val)


Во втором случае деструктор tmp вызовется все равно, но только после того как будет создан временный объект в месте использования.
There are 10 types of people in the world, those who don't understand binaries, those who do, and those who understand not only binaries.
Re: Операторы в C++
От: Sergey Россия  
Дата: 20.01.03 15:43
Оценка:
Здравствуйте, Vigen, Вы писали:

V>Есть класс mpint (multi precision integer). Соответственно имплементированны операторы суммы, вычитания, умножения и т.д.. Память для хранения данных резервируется в классе динамически. И тут-то номер! Вызывая оператор сложения получаем ошибку с памятью. Пример:


V>

V>mpint a("123"), b("1AF"), c;
V>c=a+b;  //не работает

V>//Из класса mpint...
V>mpint::operator+(mpint &val)
V>{
V>   mpint tmp(this);
V>   //здесь код сложения
V>   return tmp;
V>}
V>


V>Ошибка в том, что до того как вернуть 'tmp' в виде суммы 'a' и 'b', вызывается деструктор 'tmp', который уничтожает результат суммы.

V>Пробуя статическое выделение памяти для хранения данных класса, ошибок с памятью нет, но это лишь кажущаяся "правильность": деструктор 'tmp' все равно вызывается. Просто эта память, выделенная изначально под 'tmp', "никто" не перезаписывает --> правильность лишь кажется...

Имхо, у тебя нет правильного конструктора копирования (а возможно, и оператора присваивания). Определенный компилятором конструктор копирования копирует содержимое класса почленно, и у тебя два объекта класса mpint (tmp и создаваемый компилятором временный объект) имеют каждый по указателю на один и тот же выделенный тобой (в объекте tmp) блок памяти. Когда привыходе из функции уничтожается tmp, указатель во временном объекте указывает на освобожденный блок памяти. Надо написать конструктор копирования (и оператор присваивания), который выделяет кусок памяти нужного размера и копирует ее содержимое.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re: Операторы в C++
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 20.01.03 15:53
Оценка:
Возможные варианты:

При возвращении зхначения из функции должны происходить:
— конструирование временного объекта посредством конструктора копирования
— вызов деструктора tmp

Конструирование копии должно сопровождаться передачей признака владения памятью объекта tmp, либо полным копированием содержимого tmp. Если памятью владеет более одного объекта, и каждый будет в деструкторе уничтожать свои данные, то это, похоже, наша ситуация.

Не приведена сигнатура оператора, но из контекста можно вывести следующие варианты:

1. mpint& mpint::operator+(mpint &)
2. /*const*/ mpint mpint::operator+(mpint &val)

Вариант 1 — неправильный, т.к. возвразщает ссылку на локальный объект, уничтожаемый при выходе из функции. Отметаем.
Вариант 2 должен возвращать по значению копию объекта tmp.

Короче, к чему я клоню: количество вызванных конструкторов (учитывая конструкторы копирования) соответствует количеству вызванных деструкторов. Соответственно, если конструктора копирования нет (не определен), то сгенерированная компилятором версия копирует почленно содержимое tmp, в результате чего копия будет указывать на данные, уничтоженные деструктором tmp.

Вывод: операторы ни при чем, проверь операторы присваивания и конструкторы копированя.
Алексей Кирдин
Re[2]: Операторы в C++
От: Vigen  
Дата: 20.01.03 15:54
Оценка:
Здравствуйте, Slamin, Вы писали:

Удалено избыточное цитирование. -- ПК.

S>Нужно:

S>
S>mpint mpint::operator+(mpint &val)
S>


S>Во втором случае деструктор tmp вызовется все равно, но только после того как будет создан временный объект в месте использования.


Я забыл это написать. У меня на самом деле так и есть: mpint mpint::operator+(mpint &val);
Re[2]: Операторы в C++
От: Vigen  
Дата: 20.01.03 15:56
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Здравствуйте, Vigen, Вы писали:


V>><...>


V>>Ошибка в том, что до того как вернуть 'tmp' в виде суммы 'a' и 'b', вызывается деструктор 'tmp', который уничтожает результат суммы.


ПК>Приведи, пожалуйста минимальный компилируемый код, на котором воспроизводится ошибка.



Там слишком много выйдет...
Re[3]: Операторы в C++
От: Slamin США  
Дата: 20.01.03 15:57
Оценка:
Здравствуйте, Vigen, Вы писали:

V>Я забыл это написать. У меня на самом деле так и есть: mpint mpint::operator+(mpint &val);


Тогда код в студию, вместе с конструкторами и деструктором
There are 10 types of people in the world, those who don't understand binaries, those who do, and those who understand not only binaries.
Re[2]: Операторы в C++
От: Vigen  
Дата: 20.01.03 15:59
Оценка:
Здравствуйте, Sergey, Вы писали:

Удалено избыточное цитирование. -- ПК.

S>Имхо, у тебя нет правильного конструктора копирования (а возможно, и оператора присваивания). <...>


Так выглядят мои конструктор копирования и оператор присваивания:

mpint(mpint *num); //копирование
void operator=(mpint &val); //присваивание


я уже начинаю предполагать, что все это из-за копирования... наверное, надо добавить следующий конструктор:

mpint(mpint &num); //копирование
Re[3]: Операторы в C++
От: Павел Кузнецов  
Дата: 20.01.03 16:03
Оценка:
Здравствуйте, Vigen, Вы писали:

V>Так выглядят мои конструктор копирования и оператор присваивания:


V>
V>mpint(mpint *num); //копирование
V>void operator=(mpint &val); //присваивание
V>


Должно быть:

void operator=(const mpint &val);


V>я уже начинаю предполагать, что все это из-за копирования... наверное, надо добавить следующий конструктор:


V>
V>mpint(mpint &num); //копирование
V>


Должно быть:

mpint(const mpint &val);
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: Операторы в C++
От: Vigen  
Дата: 20.01.03 16:06
Оценка:
ВСЕ РАБОТАЕТ С КОНСТРУКТОРОМ КОПИРОВАНИЯ В ВИДЕ mpint::mpint(mpint &val)!!!!!

БОЛЬШОЕ СПАСИБО ВСЕМ, КТО ПРИНЯЛ УЧАСТИЕ И ПОМОГ!!!!!! ВЫ — !!!

Виген
Re[4]: Операторы в C++
От: Vigen  
Дата: 20.01.03 16:08
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Должно быть:

ПК>
ПК>mpint(const mpint &val);


Спасибо Павел! Это было необходимо!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.