Привет всем!!!
Заранее благодарю за чтение сообщения и ответ!
Меня шокировало то, что я узнал продеббагив в ассемблерном коде прожку (пишу м 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', "никто" не перезаписывает --> правильность лишь кажется...
Пожалуйста, объясните мне смысл операторов +, -, / и т.д., если всегда вызывается деструктор!!! Или может я вообще ничего не понимаю....
Большое спасибо!!!
Виген
Здравствуйте, Vigen, Вы писали:
V><...>
V>Ошибка в том, что до того как вернуть 'tmp' в виде суммы 'a' и 'b', вызывается деструктор 'tmp', который уничтожает результат суммы.
Приведи, пожалуйста минимальный компилируемый код, на котором воспроизводится ошибка.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, 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 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
При возвращении зхначения из функции должны происходить:
— конструирование временного объекта посредством конструктора копирования
— вызов деструктора tmp
Конструирование копии должно сопровождаться передачей признака владения памятью объекта tmp, либо полным копированием содержимого tmp. Если памятью владеет более одного объекта, и каждый будет в деструкторе уничтожать свои данные, то это, похоже, наша ситуация.
Не приведена сигнатура оператора, но из контекста можно вывести следующие варианты:
Вариант 1 — неправильный, т.к. возвразщает ссылку на локальный объект, уничтожаемый при выходе из функции. Отметаем.
Вариант 2 должен возвращать по значению копию объекта tmp.
Короче, к чему я клоню: количество вызванных конструкторов (учитывая конструкторы копирования) соответствует количеству вызванных деструкторов. Соответственно, если конструктора копирования нет (не определен), то сгенерированная компилятором версия копирует почленно содержимое tmp, в результате чего копия будет указывать на данные, уничтоженные деструктором tmp.
Вывод: операторы ни при чем, проверь операторы присваивания и конструкторы копированя.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Здравствуйте, Vigen, Вы писали:
V>><...>
V>>Ошибка в том, что до того как вернуть 'tmp' в виде суммы 'a' и 'b', вызывается деструктор 'tmp', который уничтожает результат суммы.
ПК>Приведи, пожалуйста минимальный компилируемый код, на котором воспроизводится ошибка.