Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
4 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 6
1

Непонятный вызов Деструкторов при создании списка

19.02.2013, 19:07. Показов 1954. Ответов 22
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Непонятный вызов Деструкторов при создании списка.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
#include <list>
#include <vector>
#include <string>
using namespace std;
 
class AAA
{
    friend ostream &operator<<(ostream &, const AAA &);
   public:
      double x;
 
      AAA(double _x)
      {
          cout << "Vizvan Konstructor\n";
          x=_x;
      }
      
      ~AAA()
      {
         cout << "Vizvan Destructor\n";
      };
};
 
ostream &operator<<(ostream &output, const AAA &aaa)
{
   output << aaa.x << ' ' << endl;
   return output;
}
 
int main()
{
   list<AAA> L;
   L.push_back(AAA(3));
   cout<<"\n";
   L.push_back(AAA(7));
   cout<<"\n";
   L.push_back(AAA(9));
   cout<<"\n";
  
   list<AAA>::iterator i;
   for(i=L.begin(); i != L.end(); ++i) 
      cout << *i; // print with overloaded operator
   
   return 0;
}
Результат работы программы:
Vizvan Konstructor
Vizvan Destructor

Vizvan Konstructor
Vizvan Destructor
Vizvan Destructor

Vizvan Konstructor
Vizvan Destructor
Vizvan Destructor
Vizvan Destructor

3
7
9
Vizvan Destructor
Vizvan Destructor
Vizvan Destructor
Vizvan Destructor

Не пойму почему деструкторы так вызываются!
Если организовать добавление объектов в список иначе, тогда понятно как вызвываются конструктор и деструкторы!

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <list>
using namespace std;
 
 
class AAA
{
   public:
      double x;
 
      AAA(double _x)
      {
          cout << "Vizvan Konstructor\n";
          x=_x;
      }
      
      ~AAA()
      {
         cout << "Vizvan Destructor\n";
      };
};
 
 
 
 
int main()
{
   list<AAA> L;
   AAA Ablob(2);
 
   Ablob.x=7;
   L.push_back(Ablob); 
 
   Ablob.x=5;
   L.push_back(Ablob);  
              
   Ablob.x=8;
   L.push_back(Ablob); 
 
   list<AAA>::iterator i;
 
   for(i=L.begin(); i != L.end(); ++i) 
       cout << (*i).x << " " << endl; 
 
   
 
   return 0;
}
Результат:
Vizvan Konstructor
7
5
8
Vizvan Destructor
Vizvan Destructor
Vizvan Destructor
Vizvan Destructor

Конструктор вызывается один раз потому, что мы создали один объект вне списка. 4-ре Деструктора вызываются по завершению проги(1-н к созданному отдельно объекту и 3-и к объектам скопированным в список).
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
19.02.2013, 19:07
Ответы с готовыми решениями:

Вызов конструкторов/деструкторов при наследовании
Объясните пожалуйста, как получается вывод на экран 2531 #include &lt;iostream&gt; class A {...

Непонятный ответ при создании двумерного массива
... Working = ,] ... tgbot().Working.append(tgbot().chatid) ...

Отладчик и вызов деструкторов
Всем привет. Как в отладчике посмотреть, были ли вызваны деструкторы локальных объектов функции?

Вызов деструкторов членов класса
у меня есть класс поля которого тоже классы...при выходе из конструктора вызывается деструктор для...

22
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
19.02.2013, 19:32 2
какой компилятор?
http://alturl.com/fvh3v
0
Эксперт по пяченькам
67 / 67 / 12
Регистрация: 16.08.2011
Сообщений: 249
19.02.2013, 19:51 3
А если попробуй добавить конструктор копирования (чтобы он не создавался по умолчанию) и добавить туда вывод и посмотри на результат.

Добавлено через 10 минут
Вот вывод для первого случая:
Кликните здесь для просмотра всего текста
Vizvan Konstructor
Vizvan Konstructor copy
Vizvan Destructor

Vizvan Konstructor
Vizvan Konstructor copy
Vizvan Destructor

Vizvan Konstructor
Vizvan Konstructor copy
Vizvan Destructor

3
7
9
Vizvan Destructor
Vizvan Destructor
Vizvan Destructor

Вот для второго:
Кликните здесь для просмотра всего текста
Vizvan Konstructor
Vizvan Konstructor copy
Vizvan Konstructor copy
Vizvan Konstructor copy
7
5
8
Vizvan Destructor
Vizvan Destructor
Vizvan Destructor
Vizvan Destructor
0
4 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 6
19.02.2013, 20:37  [ТС] 4
какой компилятор?
Microsoft Visual Studio 2010
0
Эксперт С++
177 / 163 / 21
Регистрация: 12.02.2013
Сообщений: 410
19.02.2013, 21:11 5
Vizvan Konstructor
Vizvan Destructor

Vizvan Konstructor
Vizvan Destructor

Vizvan Konstructor
Vizvan Destructor

3
7
9
Vizvan Destructor
Vizvan Destructor
Vizvan Destructor

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

P.S. собирал в 2008 студии - не думаю, что это имеет смысл
0
4 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 6
19.02.2013, 22:09  [ТС] 6
а это код не со списком, а с вектором выдал те деструкторы, а со списком да выдает
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Vizvan Konstructor
Vizvan Destructor
 
Vizvan Konstructor
Vizvan Destructor
 
Vizvan Konstructor
Vizvan Destructor
 
3
7
9
Vizvan Destructor
Vizvan Destructor
Vizvan Destructor
с вектором
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
   vector<AAA> L;
   
   L.push_back(AAA(3));
   cout<<"\n";
   L.push_back(AAA(7));
   cout<<"\n";
   L.push_back(AAA(9));
   cout<<"\n";
  
   vector<AAA>::iterator i;
   for(i=L.begin(); i != L.end(); ++i) 
      cout << *i; // print with overloaded operator
   
   return 0;
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Vizvan Konstructor
Vizvan Destructor
 
Vizvan Konstructor
Vizvan Destructor
Vizvan Destructor
 
Vizvan Konstructor
Vizvan Destructor
Vizvan Destructor
Vizvan Destructor
 
3 
7 
9 
Vizvan Destructor
Vizvan Destructor
Vizvan Destructor
что за фигня?
0
ComfyMobile
401 / 282 / 34
Регистрация: 24.07.2012
Сообщений: 916
19.02.2013, 22:19 7
UACrimea, почитайте внимательно коментарий StasGamilton, все популярно объяснил же
0
Эксперт С++
177 / 163 / 21
Регистрация: 12.02.2013
Сообщений: 410
19.02.2013, 22:36 8
УУУУУРРРРРАААААААА!!!

Докопался) Вот в чем замес, смари:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
vector<AAA> L;  
     
   L.reserve(3);
 
   L.push_back(AAA(3));
   cout<<"\n";
   
   L.push_back(AAA(7));
   cout<<"\n";
 
   L.push_back(AAA(9));
   cout<<"\n";
     
   return 0;
Т.е. проблема была в том, что вектор каждый раз перераспределял память, когда требовалось добавить еще один элемент. Т.е. выделял по-новой память на 1 больше, для того, чтобы новый элемент поместился. Ну а старую, соответственно, удалял, отчего деструктор вызывался при push_back один раз - для временного объекта и еще для каждого, что до этого уже имелись в векторе, как следствие перераспределения памяти. Если зарезервировать нужное/или большее кол-во мест в памяти - таких издержек не будет. Кстати, это один из примеров оптимального использования vector.


Вот вывод, такой же, как и для списка. Но список не требует перераспределения памяти по понятным соображениям)
Vizvan Konstructor
Vizvan Destructor.

Vizvan Konstructor
Vizvan Destructor.

Vizvan Konstructor
Vizvan Destructor.

Vizvan Destructor.
Vizvan Destructor.
Vizvan Destructor.
1
4 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 6
20.02.2013, 00:47  [ТС] 9
ITcrusader
Отличный ответ
Спасибо!
Терь понятно.
Т.е. получается что без функции reserve, vector добавляет элемент медленне чем list!?
0
Эксперт С++
177 / 163 / 21
Регистрация: 12.02.2013
Сообщений: 410
20.02.2013, 10:15 10
Да, верно.
Но по-настоящему можно прочувствовать проблему НЕиспользования reserve для данного сценария заполнения вектора, когда кол-во добавляемых туда элементов велико. Т.е. добавление уже, скажем, 1000-го элемента влечет накладные расходы по удалению каждого из 999 элементов, уже имеющихся там! Кроме того, еще и накладные расходы на удаление самой области памяти, отведенной под элементы вектора и выделение новой области памяти под кол-во элементов, на единицу большее! Операции эти - самые дорогие в C++ по времени выполнения. Короче, reserve - must be used для vector, особенно, если он расчитан на хранение потенциально очень большого числа элементов

P.S. Спасибо за вопрос - один из самых интересных для меня из решенных
0
4 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 6
20.02.2013, 10:18  [ТС] 11
Хотя стоп. А какой смысл в vector с функцией reserve? Ведь это динамический массив. С тем же успехом, обычный массив можно создать!
0
Эксперт С++
177 / 163 / 21
Регистрация: 12.02.2013
Сообщений: 410
20.02.2013, 10:27 12
UACrimea, функция reserve не требует от тебя точной цифры, декларирующей кол-во элементов, которое будет находиться в векторе, поэтому, если ты знаешь, что это кол-во не превысит N - ты можешь задать N, как аргумент reserve. При этом перераспределения не будет происходить, пока ты не начнешь совать туда (N+1)-й элемент))) Преимущество по-сравнению с массивом? Ну, ты не сможешь написать аналогичный сценарий для массива, потому как он НЕ динамически-расширяем. Т.е. ты можешь работать с вектором, не зная сколько тебе в него надо будет запихать элементов, но предварительно зарезервировав память. А массив тебе придется создавать полностью с указанием размера и при создании каждый из элементов массива будет создан посредством вызова своего конструктора по умолчанию. Кроме того, вектор берет на себя управление памятью.
0
ComfyMobile
401 / 282 / 34
Регистрация: 24.07.2012
Сообщений: 916
20.02.2013, 10:40 13
ну а если суешь уже N+1 то зарезервируй еше N слотов, чтобы наверняка,а потом пустые очисть
C++
1
vector::shrink_to_fit
0
512 / 464 / 81
Регистрация: 07.04.2012
Сообщений: 869
Записей в блоге: 1
20.02.2013, 10:46 14
Цитата Сообщение от ITcrusader Посмотреть сообщение
Т.е. проблема была в том, что вектор каждый раз перераспределял память, когда требовалось добавить еще один элемент.
Справедливости ради, стоит отметить, что емкость обычно увеличивается не на 1 элемент, а вдвое, как в примере:

C++
1
2
3
4
5
6
7
vector<int> v;
 
for(int i = 1; i <= 50; ++i)
{
    v.push_back(1);
    cout << i << ": " << v.capacity() << "\n";
}
0
Эксперт С++
177 / 163 / 21
Регистрация: 12.02.2013
Сообщений: 410
20.02.2013, 10:58 15
Schizorb, не совсем справедливое замечание. Вопросы расширения ёмкости, мне думается - на усмотрении реализации.

Вот, что выводит у меня (MVS 2010) при запуске примера:

1: 1
2: 2
3: 3
4: 4
5: 6
6: 6
7: 9
8: 9
9: 9
10: 13
........
13: 13
14: 19
........
19: 19
20: 28
........
28: 28
29: 42
........
42: 42
43: 63
........
50: 63

1. Не сказал бы, что вдвое.
2. В контексте заданного вопроса (при работе с 3-мя элементами), как раз таки моя (и его) реализации увеличивают на единицу
0
512 / 464 / 81
Регистрация: 07.04.2012
Сообщений: 869
Записей в блоге: 1
20.02.2013, 11:12 16
Цитата Сообщение от ITcrusader Посмотреть сообщение
Вопросы расширения ёмкости, мне думается - на усмотрении реализации.
Видимо, так и есть. Но суть в том, что не каждый раз по одному дополнительному элементу выделяется. На gcc получилось вдвое, а студия как-то интересно перераспределение делает
1
Эксперт С++
177 / 163 / 21
Регистрация: 12.02.2013
Сообщений: 410
20.02.2013, 11:18 17
Ага, ну в любом случае, целесообразно все же использовать reserve)

Кстати, по эффективному использованию STL есть потрясающая книга. Я нахожу её очень интересной.
Скотт Мейерс, Эффективное использование STL. Рекомендую
1
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
20.02.2013, 11:37 18
Емкость расширяется по закону золотого сечения. Только не самому сечению, а близкому к нему значению
0
Эксперт С++
177 / 163 / 21
Регистрация: 12.02.2013
Сообщений: 410
20.02.2013, 11:53 19
Вероятно, этот закон носит размытый характер)))

Мы только что убедились в том, что некоторые реализации делают это в соответствии со 2-м законом Ньютона Уверен, если покопаться, можно найти реализации в соответствии с законом Бойля-Мариотта и др.

Что можно сказать с уверенностью, полагаться на то, что это делается "так, а не иначе" - нельзя.
0
1373 / 596 / 199
Регистрация: 02.08.2011
Сообщений: 2,882
20.02.2013, 12:01 20
Цитата Сообщение от ITcrusader Посмотреть сообщение
у, ты не сможешь написать аналогичный сценарий для массива, потому как он НЕ динамически-расширяем
статический массив да, он вообще не расширяем
динамический массив расширить легко.
0
20.02.2013, 12:01
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.02.2013, 12:01
Помогаю со студенческими работами здесь

Наследование - вызов конструкторов и деструкторов
Делаю два класса - предок и потомок: class class_1_type { private: int t; public: ...

Вызов лишних конструкторов и деструкторов в std::vector
почему вызывает лишние конструкторы и вообще делает не то, что ожидаешь class S { public: int...

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

Почему происходит вызов OnKlick при создании Button
Привет есть XML файл с диалогами есть панель где пишутся диалоги есть панел где появляются...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru