Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
 
UACrimea
4 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 6
19.02.2013, 19:07     Непонятный вызов Деструкторов при создании списка #1
Непонятный вызов Деструкторов при создании списка.

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-и к объектам скопированным в список).
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
19.02.2013, 19:32     Непонятный вызов Деструкторов при создании списка #2
какой компилятор?
http://alturl.com/fvh3v
StasGamilton
Эксперт по пяченькам
 Аватар для StasGamilton
67 / 67 / 1
Регистрация: 16.08.2011
Сообщений: 258
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
UACrimea
4 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 6
19.02.2013, 20:37  [ТС]     Непонятный вызов Деструкторов при создании списка #4
какой компилятор?
Microsoft Visual Studio 2010
ITcrusader
Эксперт C++
 Аватар для ITcrusader
176 / 162 / 8
Регистрация: 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 студии - не думаю, что это имеет смысл
UACrimea
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
что за фигня?
Nixy
ComfyMobile
 Аватар для Nixy
399 / 280 / 8
Регистрация: 24.07.2012
Сообщений: 916
19.02.2013, 22:19     Непонятный вызов Деструкторов при создании списка #7
UACrimea, почитайте внимательно коментарий StasGamilton, все популярно объяснил же
ITcrusader
Эксперт C++
 Аватар для ITcrusader
176 / 162 / 8
Регистрация: 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.
UACrimea
4 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 6
20.02.2013, 00:47  [ТС]     Непонятный вызов Деструкторов при создании списка #9
ITcrusader
Отличный ответ
Спасибо!
Терь понятно.
Т.е. получается что без функции reserve, vector добавляет элемент медленне чем list!?
ITcrusader
Эксперт C++
 Аватар для ITcrusader
176 / 162 / 8
Регистрация: 12.02.2013
Сообщений: 410
20.02.2013, 10:15     Непонятный вызов Деструкторов при создании списка #10
Да, верно.
Но по-настоящему можно прочувствовать проблему НЕиспользования reserve для данного сценария заполнения вектора, когда кол-во добавляемых туда элементов велико. Т.е. добавление уже, скажем, 1000-го элемента влечет накладные расходы по удалению каждого из 999 элементов, уже имеющихся там! Кроме того, еще и накладные расходы на удаление самой области памяти, отведенной под элементы вектора и выделение новой области памяти под кол-во элементов, на единицу большее! Операции эти - самые дорогие в C++ по времени выполнения. Короче, reserve - must be used для vector, особенно, если он расчитан на хранение потенциально очень большого числа элементов

P.S. Спасибо за вопрос - один из самых интересных для меня из решенных
UACrimea
4 / 0 / 0
Регистрация: 19.02.2013
Сообщений: 6
20.02.2013, 10:18  [ТС]     Непонятный вызов Деструкторов при создании списка #11
Хотя стоп. А какой смысл в vector с функцией reserve? Ведь это динамический массив. С тем же успехом, обычный массив можно создать!
ITcrusader
Эксперт C++
 Аватар для ITcrusader
176 / 162 / 8
Регистрация: 12.02.2013
Сообщений: 410
20.02.2013, 10:27     Непонятный вызов Деструкторов при создании списка #12
UACrimea, функция reserve не требует от тебя точной цифры, декларирующей кол-во элементов, которое будет находиться в векторе, поэтому, если ты знаешь, что это кол-во не превысит N - ты можешь задать N, как аргумент reserve. При этом перераспределения не будет происходить, пока ты не начнешь совать туда (N+1)-й элемент))) Преимущество по-сравнению с массивом? Ну, ты не сможешь написать аналогичный сценарий для массива, потому как он НЕ динамически-расширяем. Т.е. ты можешь работать с вектором, не зная сколько тебе в него надо будет запихать элементов, но предварительно зарезервировав память. А массив тебе придется создавать полностью с указанием размера и при создании каждый из элементов массива будет создан посредством вызова своего конструктора по умолчанию. Кроме того, вектор берет на себя управление памятью.
Nixy
ComfyMobile
 Аватар для Nixy
399 / 280 / 8
Регистрация: 24.07.2012
Сообщений: 916
20.02.2013, 10:40     Непонятный вызов Деструкторов при создании списка #13
ну а если суешь уже N+1 то зарезервируй еше N слотов, чтобы наверняка,а потом пустые очисть
C++
1
vector::shrink_to_fit
Schizorb
 Аватар для Schizorb
508 / 460 / 16
Регистрация: 07.04.2012
Сообщений: 865
Записей в блоге: 1
Завершенные тесты: 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";
}
ITcrusader
Эксперт C++
 Аватар для ITcrusader
176 / 162 / 8
Регистрация: 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-мя элементами), как раз таки моя (и его) реализации увеличивают на единицу
Schizorb
 Аватар для Schizorb
508 / 460 / 16
Регистрация: 07.04.2012
Сообщений: 865
Записей в блоге: 1
Завершенные тесты: 1
20.02.2013, 11:12     Непонятный вызов Деструкторов при создании списка #16
Цитата Сообщение от ITcrusader Посмотреть сообщение
Вопросы расширения ёмкости, мне думается - на усмотрении реализации.
Видимо, так и есть. Но суть в том, что не каждый раз по одному дополнительному элементу выделяется. На gcc получилось вдвое, а студия как-то интересно перераспределение делает
ITcrusader
Эксперт C++
 Аватар для ITcrusader
176 / 162 / 8
Регистрация: 12.02.2013
Сообщений: 410
20.02.2013, 11:18     Непонятный вызов Деструкторов при создании списка #17
Ага, ну в любом случае, целесообразно все же использовать reserve)

Кстати, по эффективному использованию STL есть потрясающая книга. Я нахожу её очень интересной.
Скотт Мейерс, Эффективное использование STL. Рекомендую
daslex
1084 / 494 / 101
Регистрация: 02.08.2011
Сообщений: 2,408
20.02.2013, 11:37     Непонятный вызов Деструкторов при создании списка #18
Емкость расширяется по закону золотого сечения. Только не самому сечению, а близкому к нему значению
ITcrusader
Эксперт C++
 Аватар для ITcrusader
176 / 162 / 8
Регистрация: 12.02.2013
Сообщений: 410
20.02.2013, 11:53     Непонятный вызов Деструкторов при создании списка #19
Вероятно, этот закон носит размытый характер)))

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

Что можно сказать с уверенностью, полагаться на то, что это делается "так, а не иначе" - нельзя.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.02.2013, 12:01     Непонятный вызов Деструкторов при создании списка
Еще ссылки по теме:

Вложенные структуры. Ошибка с создании вложенного двунаправленного списка C++
C++ Вызов конструкторов/деструкторов при наследовании
C++ Ошибка в создании списка

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

Или воспользуйтесь поиском по форуму:
daslex
1084 / 494 / 101
Регистрация: 02.08.2011
Сообщений: 2,408
20.02.2013, 12:01     Непонятный вызов Деструкторов при создании списка #20
Цитата Сообщение от ITcrusader Посмотреть сообщение
у, ты не сможешь написать аналогичный сценарий для массива, потому как он НЕ динамически-расширяем
статический массив да, он вообще не расширяем
динамический массив расширить легко.
Yandex
Объявления
20.02.2013, 12:01     Непонятный вызов Деструкторов при создании списка
Ответ Создать тему
Опции темы

Текущее время: 17:10. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru