Перейти из форума на сайт.

НовостиФайловые архивы
ПоискАктивные темыТоп лист
ПравилаКто в on-line?
Вход Забыли пароль? Первый раз на этом сайте? Регистрация
Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » деструкторы в С++

Модерирует : ShIvADeSt

 Версия для печати • ПодписатьсяДобавить в закладки

Открыть новую тему     Написать ответ в эту тему

sergsd

Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Здравствуйте.
Недавно начал изучать C++ в ВС v3.1. Появлися неболшой вопрос.
Непонятно: Если в программе(см. ниже) используется конструктор, то он вызывает в
такой последовательности:
1) Для объекта объявленного в main()     назовем ОБ1
2) Для объекта объявленного в фу-ии get()  --||-- ОБ2
После того как фу-ия get() возвращает значение выз-ся деструктор для ОБ2,
далее вызывается деструктор для временного объекта, который возвращался
фу-ей get(), назовем его ОБ3, потом деструтор для ОБ1. Так вот, вопрос в том,
что если не создавать констуктор, деструктор для ОБ3 не вызывается, хотя сам объект ОБ3 создается, это можно проверить вызвав get().thisis(), почему конструтор влияет на вызов деструтора?  
 
КОД:
#include <iostream.h>
#include <conio.h>
class ob {
 int x,y;
 static int i;
 public:
  void set_k(int a,int b) { x=a; y=b; }
  void thisis() { ob *name=this; cout<<name<<endl; }
  void show() { cout<<"x+y="<<x+y<<"\n";  }
  ob() { ob *name=this; cout<<"конструктор "<<name<<"\n"; }
  ~ob() {ob *name=this; cout<<"деструктор "<<name<<"\n"; }
};
 
ob get() {
 ob s;
 cout<<"this in get()=";
 s.thisis();
 int x,y;
 cout<<"x=";
 cin>>x;
 cout<<"y=";
 cin>>y;
 s.set_k(x,y);
 return s;
}
 
int main() {
 clrscr();
 ob k;
 k=get();  //закоментировать эту строку, если раском. нижнюю
// get().thisis();
 k.show();
 while(!kbhit());
 return 0;
}
 

Всего записей: 273 | Зарегистр. 20-06-2003 | Отправлено: 21:25 15-02-2004
Valex



Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
sergsd
1. Объект в функции get() объявляется в пределах видимости этой функции. Когда функция завершается, этот объект выходит за пределы видимости и разрушается автоматически, деструктор вызывается для этого объекта.
2. В функции main() создается объект k, значения этого объекта приравниваются к s, когда эта функция завершается, вызывается деструктор для объекта k и объект уничтожается. Т.е. сколько объектов  объявляется, столько и уничтожается, никакого третьего объекта там нет

Всего записей: 61 | Зарегистр. 21-09-2001 | Отправлено: 07:42 16-02-2004
sergsd

Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Valex, спасибо за ответ, но третий объект там все же есть, если верить результату выполнения программы и Герберту Шилдту  
Можешь скачать его учебник по адрессу http://khpi-iip.mipk.kharkiv.edu/library/copy.html он там в самом низу, тебе, видимо, тоже полезно будет.
Запусти код в таком виде, какой приведен выше и увидешь результат, который доказывает, что все же третий объект есть.
Результат:
конструктор 0xfff2
конструктор 0xffe2
this in get()=oxffe2
x=3
y=4
деструктор 0xffe2
деструктор 0xffee
x+y=7
деструктор 0xfff2  
 
Как видишь, адресс 0xffee и есть адресс третего объекта.  То, что именно этот адресс и есть адресс третего объекта, который передает значения объекту k подтверждает вызов get().thisis().  
 
ТОЕСТЬ ВОПРОС ОТСАЛСЯ ОТКРЫТЫМ. И раз уж я привел результат кода, то продолжу. И отчасти пвоторю свой вопрос:
Допустим, что в вышеприведенном коде стерли строку ob() { ob *name=this; cout<<"конструктор "<<name<<"\n"; }, тогда результат программы будет такоим.
Результат:  
this in get()=0xffea
x=3
y=4
деструктор 0xffea
x+y=7
деструктор 0xfff2
 
Как видите деструктор для временного объекта уже не вызывается. Сначала я думал, что он(объект) и не создается, но создал фу-ию thisis()  чтобы проверить так ли это. Теперь закоментируем строку k=get(); и разкоментируем строку //get().thisis(); , конструктор оставим стертым.
Реузльтат:  
this in get()=0xffe6
x=3
y=4
деструктор 0xffe6
0xffee
x+y=6448
деструктор 0xfff2
 
Результат программы неправильный, т.к. объекту k мы ничего не передовали, но строка 0xffee подтверждает, что третий временный объект все же создается.
 
Так вот, повторяюсь, непонятно: почему, когда я убираю конструктор, деструктор для этого третьего временного объекта не вызывается?
 

Всего записей: 273 | Зарегистр. 20-06-2003 | Отправлено: 21:08 16-02-2004 | Исправлено: sergsd, 18:58 19-02-2004
Bloody_Nokia_Adept



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
sergsd
Дык... У тебя в проге и создается три объекта класса ob:
1. переменная k в функции main
2. переменная s в функции get()
3. автопеременная, возвращаемая функцией get()
Вот они красавцы, все три
Дело в том, что твоя (или Шилдта) реализация не учитывает такую штуку, как конструктор копирования. Добавть в класс ob следующий метод:

Цитата:
ob(const ob& _other) { ob *name=this; *this = _other; cout<<"конструктор копирования "<<name<<"\n"; }

и ты увидишь конструирование "недостающего" объекта
 
PS: имхо, все же лучше начинать со Страуструпа изучать С++.

Всего записей: 785 | Зарегистр. 27-11-2002 | Отправлено: 23:18 16-02-2004
mihas83



Gold Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Bloody_Nokia_Adept

Цитата:
что твоя (или Шилдта) реализация не учитывает такую штуку, как конструктор копирования.

Совершенно верно... При чем, компилятор генерирует его неявно, если он тобой не определен...

Всего записей: 7832 | Зарегистр. 15-07-2003 | Отправлено: 09:14 17-02-2004
sergsd

Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Bloody_Nokia_Adept, спасибо большое за ответ.

Цитата:
и ты увидишь конструирование "недостающего" объекта  

С конструктороами мне все ясно, мне не понятно, почему, если я объявляю конструктор, то деструктор для этой автопеременной вызывается, а когда конструктор не объявлен, то уже и деструктор не вызывается?

Всего записей: 273 | Зарегистр. 20-06-2003 | Отправлено: 19:21 17-02-2004
Bloody_Nokia_Adept



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
sergsd

Цитата:
С конструктороами мне все ясно, мне не понятно, почему, если я объявляю конструктор, то деструктор для этой автопеременной вызывается, а когда конструктор не объявлен, то уже и деструктор не вызывается?

Бредовая ситуация... Если не объявлен конструктор, то компилятором используется конструктор по умолчанию и это никак не сказывается на вызове деструктора - сколько объектов создано, столько деструкторов и будет вызвано.
 
ВС v3.1, если мне не изменяет память, датируется 1993-1994 годом, т.е. в нем нет поддержки стандарта С++ 1998 года и нет stl. К тому же ребята из Borland всегда любили авторские разработки и ставили их выше стандартов (на ту пору действующим был стандарт 1989 года).
 
Как результат от него можно ждать чудес.
 
Мне не понятно желание изучать С++ с использованием этой среды и как альтернативу мог бы предложить вариант компилятора MinGW v3.1 (порт gcc v3.1 на платформу DOS/Windows) в связке с Far/Colorer (редактор с подсветкой синтаксиса С++). А в качестве stl использовать stlport или на худой конец sgi/hp (они не хуже stlport, но он на них основан и нормально портирован на большинство платформ).
 
Тогда уже можно будет нормально компилиться и получать ожидаемые результаты, а не гадать на кофейной гуще о связи конструкторов и деструкторов.
 
PS: Надеюсь, что мои слова не обидели Вас, т.к. ВС v3.1 уже отслужил свой век и его эпоха закончилась еще 10 лет назад.

Всего записей: 785 | Зарегистр. 27-11-2002 | Отправлено: 00:50 18-02-2004
sergsd

Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Bloody_Nokia_Adept, благодарю за ответ.

Цитата:
Бредовая ситуация... Если не объявлен конструктор, то компилятором используется конструктор по умолчанию и это никак не сказывается на вызове деструктора - сколько объектов создано, столько деструкторов и будет вызвано.  

Так вот мне и было(и есть) не понятно почему конструктор влияет на вызов деструктора.  
Если Вам несложно, могли бы Вы написать результат выполнения такого кода в вашем компиляторе, так как сам под рукой другого не имею. Хочу убедиться, что проблема действительно в BC++ 3.1 .
Код:
#include <iostream>  
#include <cconio>  
using namespace std;
 
class ob {  
 int x,y;  
 static int i;  
 public:  
  void set_k(int a,int b) { x=a; y=b; }  
  void thisis() { ob *name=this; cout<<name<<endl; }  
  void show() { cout<<"x+y="<<x+y<<"\n";  }  
  ~ob() {ob *name=this; cout<<"деструктор "<<name<<"\n"; }  
};  
 
ob get() {  
 ob s;  
 cout<<"this in get()=";  
 s.thisis();  
 int x,y;  
 cout<<"x=";  
 cin>>x;  
 cout<<"y=";  
 cin>>y;  
 s.set_k(x,y);  
 return s;  
}  
 
int main() {  
 clrscr();  
 ob k;  
 k=get();  
 k.show();  
 while(!kbhit());  
 return 0;  
}  
 

Цитата:
Мне не понятно желание изучать С++ с использованием этой среды и как альтернативу мог бы предложить вариант компилятора MinGW v3.1 (порт gcc v3.1 на платформу DOS/Windows) в связке с Far/Colorer (редактор с подсветкой синтаксиса С++). А в качестве stl использовать stlport или на худой конец sgi/hp (они не хуже stlport, но он на них основан и нормально портирован на большинство платформ).  

 
Это объясняется легко. Во-первых, я просто привык к нему, изучая в нем азы C. Во-вторых, мне нравится его среда и нетормознутость, как более поздних windows-версий.  
И наконец, начинающему довольно сложно определиться и выбрать какой-либо из множества компиляторов, например, что выбрать Buidler С++ или Visual С++ под windows.
Выбор на будущее я сделал на данный момент такой: Watcom в DOS/WIN и gcc в UNIX/Linux, хотя думаю, что сюда придется добавить один из вышенаписанных. Но так в UNIX/Linux я еще далеко даже не уверенный пользователь, то gcc решил отложит до тех пор, пока нормально освою Linux, а с Watcom-ом довольно долго разбираться, да и литературы по нему не имеется, поэтому и решил, что пока, чтобы освоить основы ООП в C++ сойдет и ВС++ 3.1.
 
Хотя совсем недавно пытался поставить gcc под windows c http://www.cygwin.com/, но это, как я понял, немного больше, чем просто компилятор. Правда посмотреть, что он из себя представляет так и не удалось: щелкнул по ссылке на сайт "Install Cygwin now" установились какие-то файлы, но ничего работающего в них не нашел Потом прочитал, что cygwin занимает 800мб(может чуть меньше, точно не помню) и понял, то, что я скачал далеко не cygwin, а скачать через модем полную версию для меня нереально, да и на сайте cygwin.com ссылка вроде только на то, что я установил, поэтому на cygwin я просто забил и решил отлажить gcc до Linux или до тех пор, пока поумнею. О MinGW v3.1 ничего не слышал, надеюсь, с ним меньше гемороя, чем с cygwin, обязательно посмотрю(если есть ссылки на русскоязычную доку по нему, буду Вам благодарен, если Вы их здесь напишите) Извиняюсь, а что такое stl ? (можно ответить и линком )

Всего записей: 273 | Зарегистр. 20-06-2003 | Отправлено: 21:18 18-02-2004
drobitko

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Вот  результат работы твоей программы при компиляции Borland C++ 5.5
 
this in get()=0012FF3C
x=1
y=2
деструктор 0012FF3C
деструктор 0012FF7C
x+y=3
деструктор 0012FF84

Всего записей: 83 | Зарегистр. 10-02-2003 | Отправлено: 16:20 19-02-2004
sergsd

Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
drobitko, спасибо.
Значит действительно дело было в BC++ 3.1

Всего записей: 273 | Зарегистр. 20-06-2003 | Отправлено: 19:01 19-02-2004
drobitko

Junior Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Да незачто!
 
Вот ссылка, отсюда можно скачать Borland C++ 5.5 компилятор. Весит 8.7 MB.
 
_http://www.borland.com/products/downloads/download_cbuilder.html#

Всего записей: 83 | Зарегистр. 10-02-2003 | Отправлено: 19:58 19-02-2004
sergsd

Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Скачал и опробовал и MinGW и Borland C++ 5.5.
MinGW понравился: небольшой, нетормозящий, оч. удобная среда разработки.
Ну о Borlcand C++ 5.5 могу только сказать, что компилятор пашет, вот кстати ссылка на этот компилятор, которую я получил после регистрации: tp://ftpd.borland.com/download/bcppbuilder/freecommandLinetools.exe
 
Возник новый вопрос.
В книге Шилдта описывается Standard C++.  
Вот отрывок из книги:

Цитата:
 
В первые несколько лет после появления C++ в нем использовался тот же стиль оформления заголовков, что и в C. Для совместимости с прежники программами в языке Standard C++ этот стиль по-прежнему поддерживается. Тем не менее при работе с библиотекой Standard C++ в соответсвии с новым стилем вместо имен заголовочных файлов указываются стандартные идентификаторы, по которым компилятор находит требуемые файлы...Т.к. новые заголовки не явл-ся именами файлов, для них не нужно указывать расширение .h, а только имя заголовка в угловых скобках. Поскольку С++ содержит всю библиотеку фу-ий C, по-прежнему поддерживается стандартный стиль оформления заголовочных файлов библиотеки С. Таким образом, такие заголовочные файлы, как stdio.h и ctype.h все еще доступны. Однако Standard C++ также определяет заголвоки нового стиля, которые можно указывать вместо этих заголовчных файлов. В соответствии с версией C++ к стандартным заголовкам С просто добавляется префикс с и удаляется расширение .h. Например, заголовко math.h Ззаменяется новым заголовком C++ <cmath>, а string.h - <cstring>.
 

Так вот, и MinGW и Borland C++ 5.5, например,  <cconio>  выдает ошибку. Почему? Что Standard C++ изменился на какой-то новый?

Всего записей: 273 | Зарегистр. 20-06-2003 | Отправлено: 21:34 20-02-2004
Bloody_Nokia_Adept



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
sergsd
Приношу извинения за длительное молчание - был по делам в Киеве.
 
То что проблемы была именно в компиляторе не вызывало сомнения с самого начала - вспомните мой пост, где я указывал на его не совместимость со стандартом.
 

Цитата:
MinGW понравился: небольшой, нетормозящий, оч. удобная среда разработки.

Та да, а главное с очень совместим со стандаротом и автоматически появятся навыки работы с gcc. К нему есть IDE, так что не обязательно сидеть в консоли.

Цитата:
Так вот, и MinGW и Borland C++ 5.5, например,  <cconio>  выдает ошибку. Почему? Что Standard C++ изменился на какой-то новый?

Нет, стандарт один (редакция от 1998 года), просто заголовочного файла такого нет - <conio.h>!
 
Книга Шилдта какого года? Именно оригинал, а не перевод.

Всего записей: 785 | Зарегистр. 27-11-2002 | Отправлено: 14:28 21-02-2004
sergsd

Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Bloody_Nokia_Adept, привет.
 

Цитата:
То что проблемы была именно в компиляторе не вызывало сомнения с самого начала - вспомните мой пост, где я указывал на его не совместимость со стандартом.  

Больше ничего на C++ я в нем делать не буду
 

Цитата:
Книга Шилдта какого года? Именно оригинал, а не перевод.

Какого года книга я не знаю, т.к. читаю ее электронный вариант, но если верить отрывку
 из книги:
Цитата:
Настоящая книга учит языку Standard C++. Эта версия C++, поределенная комитетом по стандартам ANSI/ISO, должна быть реализована во всех современных компиляторах C++. Пример программ этой книги отражают современный стиль программирования в соответсвии с новыми реалиями языка Standart C++. Это означает актуальность содержания книги не только сегодня, но и в будущем...

выходит, что он пишет как раз о последнем стандарте.
 

Цитата:
Нет, стандарт один (редакция от 1998 года), просто заголовочного файла такого нет - <conio.h>!  

Опять же, если верить Шилдту(см. мой предыдущий пост), заголовки не являются именами файлов, а вместо них указываются стандартные идентификаторы, а  к стандартным заголовкам С просто добавляется префикс с и удаляется расширение .h. Но выходит, что это все же не так и для стандартных заголовков C нужно указывать имя заголовчного файла.
#include <conio.h>  -- работает везде
#include <cconio>  -- нигде
 
PS: А кто, что скажет о книге "Объектно-ориентированное программирование в С++. Классика Computer Science" Лафоре Р.  Издание: 4-е ?

Всего записей: 273 | Зарегистр. 20-06-2003 | Отправлено: 16:46 21-02-2004
Bloody_Nokia_Adept



Advanced Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
sergsd

Цитата:
Опять же, если верить Шилдту(см. мой предыдущий пост), заголовки не являются именами файлов, а вместо них указываются стандартные идентификаторы, а  к стандартным заголовкам С просто добавляется префикс с и удаляется расширение .h.

Для части заголовочных файлов это сделали, а для большинства нет - зачем огород городить?

Цитата:
А кто, что скажет о книге

Ничего не скажу, но повторю свое мнение - эти книги от лукавого!
Вот мои учебники C++:
1. The C++ Programming Language / Bjarne Stroustrup. — 3rd. ed., 1997
2. INTERNATIONAL STANDARD ISO/IEC 14882 - Programming languages — C++ - First edition
1998-09-01
3. БИБЛИОТЕКА ПРОГРАММИСТА C++ / Джефф Элджер
4. Modern C++ Design: Generic Programming and Design Patterns Applied / Andrei Alexandrescu. - 2001
5. Efficient C++ Performance Programming Techniques / Dov Bulka, David Mayhew - 1999
Вот... Эти источники и именно в таком порядке помогли мне.

Всего записей: 785 | Зарегистр. 27-11-2002 | Отправлено: 20:54 21-02-2004
sergsd

Member
Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору
Bloody_Nokia_Adept, благодарю за помощь.
Страуструпа обязательно прочитаю, остальные тоже, если найду их на русском

Всего записей: 273 | Зарегистр. 20-06-2003 | Отправлено: 19:22 23-02-2004
Открыть новую тему     Написать ответ в эту тему

Компьютерный форум Ru.Board » Компьютеры » Прикладное программирование » деструкторы в С++


Реклама на форуме Ru.Board.

Powered by Ikonboard "v2.1.7b" © 2000 Ikonboard.com
Modified by Ru.B0ard
© Ru.B0ard 2000-2024

BitCoin: 1NGG1chHtUvrtEqjeerQCKDMUi6S6CG4iC

Рейтинг.ru