Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Архив форумов ЦИТФорума
Море(!) вопросов - Море(!) ответов
 
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ГруппыГруппы   РегистрацияРегистрация 
 ПрофильПрофиль   Войти и проверить личные сообщенияВойти и проверить личные сообщения   ВходВход 
Как правильно задавать вопросы

Проблема с присваиванием

 
Перейти:  
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Программирование
Предыдущая тема :: Следующая тема  
Автор Сообщение
Вадим
Гость





СообщениеДобавлено: Чт Мар 21 2002 17:45    Заголовок сообщения: Проблема с присваиванием Ответить с цитатой

Имеется некоторый класс Aclass в котором одним из полей является указатель P на некоторые данные. При инициализации объекта X данного класса деляется что-нибудь подобное P=New float[10];
В деструкторе разумеется пишется
delete P;
Имеется некоторая функция возвращающая значение типа Aclass;
Теперь пишем
Aclass X;
Aclass func()
{Aclass Y;
Y.P[1]=100;
return Y;
}
Если записать
X=func();
то это присвоение не выполняется потому, что объект Y уничтожается при возврате, а это значит выполняется delete P;
Поэтому, хотя все поля копируются из Y в X содержимое массива *P уничтожается раньше, чем происходит присваивание. Как посторить объекты с динамическими полями которые можно было бы присваивать таким образом.
Вернуться к началу
JekLove



Зарегистрирован: 22.02.2002
Сообщения: 41
Откуда: Новосибирск

СообщениеДобавлено: Чт Мар 21 2002 18:28    Заголовок сообщения: Re: Проблема с присваиванием Ответить с цитатой

Во-первых:
если ты создаешь динамический массив, ты должен пользоваться операторо delete[] а не delete.

При возврате класса ничего раньше времени не удаляется. Почему ты так думаешь? Наверно, потому, что ты неправильно делаешь это присваивание. Тебе надо написать свой operator=, в котором у объекта-приемника создается свой массив P, и данные надо копировать вручную.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Alexy



Зарегистрирован: 22.10.2003
Сообщения: 48

СообщениеДобавлено: Чт Мар 21 2002 22:04    Заголовок сообщения: Re: Проблема с присваиванием Ответить с цитатой

Вообще-то Aclass:Razz действительно
уничтожается до того как будет вызван
Aclass& operator = (const Aclass&);

И вот почему:
В С++ есть ф-ции, которые любой класс получает в подарок от компилятора (при определённых условиях).
Среди этих ф-й - конструктор копирования.
Вот он:
Class::Class(const Class& other)
{
memcpy(this, &other, sizeof(Class));
}

Т.е. при
Aclass x;
Aclass y(x);
x:Razz и y:Razz будут иметь общий пойнтер, т.е. x:Razz и y:Razz будут указывать на один итот же адрес. А в случае
Aclass* Y;
{
Aclass x;
y = new Aclass(x);
} // end of scope, so call destructor for x
y:Razz указывает на освобождённую память.
И это то, что происходит в твоём примере.
Aclass fun() { Aclass y; return y; }
означает:
1. Сконструлить инстанс Aclass в стеке ( это y)
2. Скопировать инстанс из стека в некую временную память.
3. Убить у
4. вернуться из функции
(продолжение в сл. постинге)
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Alexy



Зарегистрирован: 22.10.2003
Сообщения: 48

СообщениеДобавлено: Чт Мар 21 2002 22:39    Заголовок сообщения: Re: Проблема с присваиванием Ответить с цитатой

Компилятор генерирует вызов деструктора для y вот зачем:

Известно, что параметры ф-й и локальные переменные содержатся в стеке.
Вот что это означает. Предположим, что на
момент начала процедуры caller()
ESP (stack pointer - регистр процессора, указывающий на вершину стека == x)
Тогда
caller()
{
Aclass instance;
...
для компилятора означает:
(pseudocode)
ESP = ESP - sizeof(Aclass);
call Aclass::Aclass(ESP /*это наш this*/);
...
Исходя из ESP(не вдаваясь в подробности) компилятор знает, что
ESP + (например) 8 == Aclass:Razz

Когда мы из ф-ции caller вызываем ф-цию fun,
параметры и локальные переменные fun
изменяют ESP, поэтому перед тем как caller
продолжит работу нужно вернуть ESP на место
(почистить стек).
Поэтому, чтобы не допустить утечки памяти,
бошенные дескрипторы ресурсов и пр. прелести
компилятор генерирует вызовы деструкторов
для всех локальных объектов перед возвратом
из ф-ции.



Выход: написать для класса собственный
copy constructor :
class Aclass {
...
Aclass(const Aclass& other)
{
...
// простое решение
this->P = new float[AR_SIZE];
memcpy(P, other.P, sizeof(float) * AR_SIZE);
...
}

более сложное решение - реализовать для
Aclass:Razz идиому smart pointer - а,
но это уже отдельная тема.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Вадим
Гость





СообщениеДобавлено: Пт Мар 22 2002 17:38    Заголовок сообщения: Фантастика, но всё заработало Ответить с цитатой

Действительно требуется конструктор копирования. Большое спасибо. Несчастные полиномы и фильтры заработали в динамическом режиме. А интересно, где такие тонкости можно прочитать.
Если что, чем смогу помогу.
Вернуться к началу
Alexy



Зарегистрирован: 22.10.2003
Сообщения: 48

СообщениеДобавлено: Вс Мар 24 2002 00:38    Заголовок сообщения: Re: Фантастика, но всё заработало Ответить с цитатой

Не за что,

B Stroustrup "The C++ Programming language"

Ira Pohl "Object-Oriented Programming
using C++"



James O. Coplien "Advanced C++
Programming Styles and Idioms"
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Показать сообщения:   
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Программирование Часовой пояс: GMT + 3
Страница 1 из 1

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


Powered by phpBB © 2001, 2002 phpBB Group
Русская поддержка phpBB

 

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 6608306, ICQ 232284597
Пресс-релизы — pr@citforum.ru
Послать комментарий
Информация для авторов
This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2006 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...