Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
Вадим Гость
|
Добавлено: Чт Мар 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: действительно уничтожается до того как будет вызван Aclass& operator = (const Aclass&);
И вот почему: В С++ есть ф-ции, которые любой класс получает в подарок от компилятора (при определённых условиях). Среди этих ф-й - конструктор копирования. Вот он: Class::Class(const Class& other) { memcpy(this, &other, sizeof(Class)); }
Т.е. при Aclass x; Aclass y(x); x: и y: будут иметь общий пойнтер, т.е. x: и y: будут указывать на один итот же адрес. А в случае Aclass* Y; { Aclass x; y = new Aclass(x); } // end of scope, so call destructor for x y: указывает на освобождённую память. И это то, что происходит в твоём примере. 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:
Когда мы из ф-ции 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: идиому 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" |
|
Вернуться к началу |
|
|
|