Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> вопрос про деструкторы! непонятно 
:(
    Опции темы
yull
Дата 24.11.2011, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 20.11.2011

Репутация: нет
Всего: нет



Объясните пожалуйста,почему деструктор не передает параметры?
И второй вопрос:  почему не может быть два деструктора?
PM MAIL   Вверх
borisbn
Дата 24.11.2011, 21:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(yull @  24.11.2011,  20:55 Найти цитируемый пост)
почему деструктор не передает параметры

Цитата(yull @  24.11.2011,  20:55 Найти цитируемый пост)
почему не может быть два деструктора?

по стандарту.

да и как выбирать, какой деструктор выбрать при delete obj; ?

Добавлено через 3 минуты и 16 секунд
Цитата(yull @  24.11.2011,  20:55 Найти цитируемый пост)
деструктор не передает параметры

тока щаз понял - куда не передаёт ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
hawk3500
Дата 24.11.2011, 22:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 246
Регистрация: 6.2.2009

Репутация: нет
Всего: 2



Деструктор должен вернуть системе область памяти, выделенную при выполнении конструктора.
По этому на входе ему никакие аргументы не требуются не нужны.
Деструктор нельзя объявлять как принимающий аргументы. 
Класс может иметь сколько угодно конструкторов (с разными наборами параметров), в том числе шаблонных, и только один) деструктор.
По сути можно сказать что деструктор есть не что иное как операция free.
Конструктор и деструктор являются функциями только с точки зрения их синтаксического описания.
Конструктор нельзя вызвать в любом месте, он всегда вызывается только в момент создания объекта.
Деструкторы тоже не совсем таак сказать функции, но их можно вызвать в любом произвольном месте.
Но есть несколько моментов которые надо учитывать:
1)конструктор выделяет область памяти под переменные класса(а не под функции-т.е. для всех классов одного и тогоже типа функии одни и теже и находятся по одному и томуже адресу).
2)при создании и инициализации указателя на класс можно и нужно пользоваться функцией delete .Исключение состовляет лишь такой случай:
Код

char *buf = new char[sizeof(T)];
  T *t = new(buf) T;
  
  t->~T();

3)код деструктора реально отрабатывает раньше функции free (class)
--------------------
воин dzen'a
PM MAIL   Вверх
yull
Дата 25.11.2011, 02:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 20.11.2011

Репутация: нет
Всего: нет



Цитата(hawk3500 @ 24.11.2011,  22:08)
Деструктор должен вернуть системе область памяти, выделенную при выполнении конструктора.
По этому на входе ему никакие аргументы не требуются не нужны.
Деструктор нельзя объявлять как принимающий аргументы. 
Класс может иметь сколько угодно конструкторов (с разными наборами параметров), в том числе шаблонных, и только один) деструктор.
По сути можно сказать что деструктор есть не что иное как операция free.
Конструктор и деструктор являются функциями только с точки зрения их синтаксического описания.
Конструктор нельзя вызвать в любом месте, он всегда вызывается только в момент создания объекта.
Деструкторы тоже не совсем таак сказать функции, но их можно вызвать в любом произвольном месте.
Но есть несколько моментов которые надо учитывать:
1)конструктор выделяет область памяти под переменные класса(а не под функции-т.е. для всех классов одного и тогоже типа функии одни и теже и находятся по одному и томуже адресу).
2)при создании и инициализации указателя на класс можно и нужно пользоваться функцией delete .Исключение состовляет лишь такой случай:
Код

char *buf = new char[sizeof(T)];
  T *t = new(buf) T;
  
  t->~T();

3)код деструктора реально отрабатывает раньше функции free (class)

Спасибо, вы мне очень помогли)
PM MAIL   Вверх
Леопольд
Дата 25.11.2011, 19:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Деструктор нужен для того что-бы освободить ресурсы, если есть. Если предполагается удалять объект по указатель или ссылке на базовый класс, тогда деструктор должен быть виртуальным, иначе деструкторы наследников не будут вызваны - неопределённое поведение.

Конструктор не выделяет память, он её инициализирует, для этого у него есть одна особенность, которой нет у других функций - список инициализации. Выглядит вот так:
Код
struct Foo
{
    Foo() : a(0), b('\n') // после двоеточия идёт список инициализации агрегированных членов класса
    {}
private:
    int a;
    char b;
}


И конструкторы и деструкторы можно вызвать в любом месте, но двойной вызов конструктора или деструктора на один и тот же адрес памяти - неопределённое поведение. Т.е. так делать нельзя:
Код
void foo()
{
    Foo * ptr = new Foo; // выделение памяти и вызов конструктора Foo::Foo на этот участок памяти
    // эквивалентно этому: Foo * ptr = malloc(sizeof(Foo)); if(!ptr) throw std::bad_alloc(); new(ptr) Foo;
    new(ptr) Foo; // второй вызов конструктора
    ptr->~Foo(); // ручной вызов деструктора
    delete ptr; // второй вызов деструктора, следом освобождение памяти 
    // эквивалентно этому: ptr->~Foo(); free(ptr);
}


Есть определённый порядок вызова конструктора/деструктора для агрегированных типов и базовых классов. Конструктор вызывается сначала для базовых классов, если есть, потом для агрегированных типов в порядке их определения в классе (но не в списке инициализации), потом для самого класса.
Порядок вызова деструктора полностью противоположен.

Это сообщение отредактировал(а) Леопольд - 26.11.2011, 09:57


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
maxim1000
Дата 25.11.2011, 19:22 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



Автоматический вызов деструктора - одна из важнейших особенностей C++.

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


--------------------
qqq
PM WWW   Вверх
hawk3500
Дата 25.11.2011, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 246
Регистрация: 6.2.2009

Репутация: нет
Всего: 2



Цитата(Леопольд @ 25.11.2011,  19:03)
Конструктор не выделяет память, он её инициализирует, для этого у него есть одна особенность, которой нет у других функций - список инициализации.

Т.е. как это не выделяет?
А кто тогда выделяет??
При создании объекта и вызове конструктора выделяется память.
А вызов конструктора без создания объекта не возможен.
--------------------
воин dzen'a
PM MAIL   Вверх
Леопольд
Дата 25.11.2011, 20:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Цитата(hawk3500 @  25.11.2011,  20:11 Найти цитируемый пост)
При создании объекта и вызове конструктора выделяется память.
Память выделяется до того как будет вызван конструктор.
Память может быть выделена в статической области данных процесса - объект "живёт" до тех пор, пока жив процесс.
На стеке - память автоматически выделяется и освобождается на стеке процесса (при вызове функций, например)
В куче - память выделяется программистом вручную, обычно при помощи оператора new. Освобождается тоже вручную, обычно при помощи оператора delete. Процесс освобождения желательно автоматизировать при помощи умных указателей.


Это сообщение отредактировал(а) Леопольд - 25.11.2011, 20:30


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
hawk3500
Дата 25.11.2011, 20:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 246
Регистрация: 6.2.2009

Репутация: нет
Всего: 2



Ага, понял  о чём вы.
--------------------
воин dzen'a
PM MAIL   Вверх
bems
Дата 25.11.2011, 23:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: нет
Всего: 88



Цитата(hawk3500 @  24.11.2011,  22:08 Найти цитируемый пост)
1)конструктор выделяет область памяти под переменные класса(а не под функции-т.е. для всех классов одного и тогоже типа функии одни и теже и находятся по одному и томуже адресу).
вроде это не обязано быть так во всех реализациях



--------------------
Обижено школьников: 8
PM MAIL   Вверх
mes
Дата 26.11.2011, 09:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(hawk3500 @  25.11.2011,  19:11 Найти цитируемый пост)
А вызов конструктора без создания объекта не возможен. 

смотрите размещающий new, который может создать объект в любой заранее выделенной памяти..



--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 26.11.2011, 10:06 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(hawk3500 @  25.11.2011,  20:11 Найти цитируемый пост)
Т.е. как это не выделяет?
А кто тогда выделяет??

компилятор подсчитывает размер класса эквивалентно сипользованию sizeof(). полученное значение передается оператору new, результат которого, используется по аналогии с placement new.
т.е. такой вот "стенд" получился:
Код

#include <iostream>
#include <sstream>
#include <iomanip>

/***************************************************************************/

std::string hex_dump(const char* buf, size_t len) {
   const unsigned char* buffer = reinterpret_cast<const unsigned char*>(buf);
   std::stringstream os;
   if ( !buffer || len <= 0 ) return os.str();

   size_t addr = 0;

   size_t n = 0, idx = 0, cnt2 = 0;
   os << std::endl;
   for ( n = 0; n < len; ++n ) {
      if ( cnt2 == 0 ) {
         os << std::setw(7) << std::setfill('0') << addr << ": ";
         addr += 16;
      }
      cnt2 = (cnt2 + 1) % 18;
      if ( cnt2 <= 16 ) {
         os << std::hex << std::setw(2) << std::setfill('0') << (size_t)buffer[n] << " ";
      } else {
         os << "  ";
         os << std::setfill(' ');
         for ( idx = n - cnt2 + 1; idx < n; ++idx) {
            if ( buffer[idx] < 32 || 126 < buffer[idx] ) {
               os << '.';
            } else {
               os << buffer[idx];
            }
         }
         os << std::endl << std::dec;
         cnt2 = 0;
         n--;
      }
   }

   os << std::setfill(' ');

   for ( idx = cnt2+1; idx <= 16 ; ++idx ) {
      os << std::setw(2) << "-- ";
   }
   os << "  ";

   for ( idx = n - cnt2; cnt2 <= 16 && idx < n; ++idx ) {
      if ( buffer[idx] < 32 || 126 < buffer[idx] ) {
         os << '.';
      } else {
         os << buffer[idx];
      }
   }
   os << std::endl;

   return os.str();
}

/***************************************************************************/

struct type {
   type()
      :i(3)
      ,d(3.14)
   {std::cout << "type ctor" << std::endl;}
   ~type()
   {std::cout << "type dtor" << std::endl;}

   int i;
   double d;
};

int main() {
   std::cout << "sizeof(type) = " << sizeof(type) << std::endl;

   char buf[sizeof(type)] = {0};
   std::cout << "before placement new:" <<
   hex_dump(buf, sizeof(type)) << std::endl;

   type* p1 = new(buf)type;

   std::cout << "after placement new:" <<
   hex_dump(buf, sizeof(type)) << std::endl;
   
   p1->~type();

   std::cout << "after delete:" <<
   hex_dump(buf, sizeof(type)) << std::endl;
}


http://liveworkspace.org/code/444383e6535a...3662995399a6cd1
вывод:
Цитата

sizeof(type) = 12
before placement new:
0000000: 00 00 00 00 00 00 00 00 00 00 00 00 -- -- -- --   ............

type ctor
after placement new:
0000000: 03 00 00 00 1f 85 eb 51 b8 1e 09 40 -- -- -- --   .......Q...@

type dtor
after delete:
0000000: 03 00 00 00 1f 85 eb 51 b8 1e 09 40 -- -- -- --   .......Q...@

обрати внимание на то, что delete применять к p1 нельзя из-за того, что он пытается вернуть выделенную память куче, в то время, как она на самом деле была выделена на стеке. а так же на то, что деструктор не затирает память, как иногда встречаются заблуждения.

Это сообщение отредактировал(а) boostcoder - 26.11.2011, 10:09
PM WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0580 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.