Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.86/29: Рейтинг темы: голосов - 29, средняя оценка - 4.86
 Аватар для Виктор_Сен
36 / 29 / 2
Регистрация: 01.08.2011
Сообщений: 176

При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О

28.10.2013, 14:18. Показов 6255. Ответов 27
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вот такой код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A
{
public:
    A(){}
    virtual ~A(){}
};
 
class C
{
public:
    C(A a){}
    ~C(){}
    C(C& c){}
};
 
int main()
{
    C c=C(A());
 
    system("pause");
    return 0;
}
Если посмотреть в отладчике, то видно, что конструктор C() вызывается 2 раза, причём второй раз конструктор копирования. Я понимаю, если бы это было с конструктором A(), т. к. A() передаётся по значению. Но ни могу понять почему именно конструктор C(). Причём если деструктор класса A сделать не виртуальным, то конструктор класса C() будет вызываться 1 раз. С чем это связано?
Миниатюры
При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О  
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
28.10.2013, 14:18
Ответы с готовыми решениями:

Конструктор вызывается один раз, а деструктор два раза
Программа для обработки исключений. Вообщем если ввести два числа и второе будет 0, то конструктор будет вызван 1 раз, а деструктор 2...

Почему при помещении объекта в list вызывается конструктор и деструктор?
Нужна помощь опытного программиста. Не могу понять почему при помещение объекта в list вызывается конструктор и деструктор. #include...

Два раза вызывается деструктор
Создал класс, в процессе выполнения программы вызвал деструктор, но когда программа завершается, деструктор вызывается повторно и вылетает...

27
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
28.10.2013, 14:41
Цитата Сообщение от Виктор_Сен Посмотреть сообщение
Но ни могу понять почему именно конструктор C().
При инициализации объекта (с) другим объектом (созданным с помощью C(A())), вызывается конструктор копирования.
0
46 / 46 / 18
Регистрация: 25.10.2011
Сообщений: 183
28.10.2013, 14:43
1. Вызывается конструктор А
2. Вызывается конструктор копий С
3. Вызывается деструктор А
Что странного?
0
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
28.10.2013, 14:51
С виртуальностью - 1 скрин, и без виртуальности - 2 скрин.
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
#include <iostream>
using namespace std;
 
class A
{
public:
    A(){cout << "A()" << endl;}
    virtual ~A(){cout << "~A()" << endl;}
};
 
class C
{
public:
    C(A a){cout << "C(A a)" << endl;}
    ~C(){ cout << "~C()" << endl;}
    C(C& c){ cout << "C(C &c)" << endl;}
};
 
int  main()
{
    C c = C(A());
 
    system("pause");
    return 0;
}
Миниатюры
При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О   При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О  
0
 Аватар для Виктор_Сен
36 / 29 / 2
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 14:51  [ТС]
Цитата Сообщение от Hunter13ua Посмотреть сообщение
1. Вызывается конструктор А
2. Вызывается конструктор копий С
3. Вызывается деструктор А
Что странного?
То, что Вы написали, НЕ странно. Странно то, что вызывается 2 раза конструктор для объекта C. На левом скриншоте это выделено
Assembler
1
2
3
4
5
6
call C::C
...
call C::C
...
call C::~C
...
0
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
28.10.2013, 14:55
Цитата Сообщение от Виктор_Сен Посмотреть сообщение
Странно то, что вызывается 2 раза конструктор для объекта C.
Что в этом странного? Первый раз просто конструктор: C(A()), второй раз конструктор копирования, для инициализации этим, созданным объектом, объекта c.
Миниатюры
При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О  
0
Диванный эксперт
Эксперт С++
 Аватар для Max Dark
2550 / 2064 / 971
Регистрация: 09.10.2013
Сообщений: 4,793
Записей в блоге: 4
28.10.2013, 15:02
C++
1
2
3
4
5
6
// код
C c = C(A());
// равносилен
A a;
C temp(a);
C c(temp);
0
 Аватар для Виктор_Сен
36 / 29 / 2
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 15:14  [ТС]
Цитата Сообщение от alsav22 Посмотреть сообщение
С виртуальностью - 1 скрин, и без виртуальности - 2 скрин.
Цитата Сообщение от alsav22 Посмотреть сообщение
При инициализации объекта (с) другим объектом (созданным с помощью C(A())), вызывается конструктор копирования.
Тут другого объекта нет. Тут только объект (с). Получается, что создаётся временный объект C(A())), потом от него инициализируется уже (c). Вот я и не понимаю, зачем это нужно, если при первом вызове конструктора объект уже есть... Как я полагаю, конструктор копирования срабатывает при инициализации объекта уже готовым объектом. Но тут получается заранее готового объекта нет. Он создаётся только для того, чтобы вызвать конструктор копирования, зачем это нужно, если при первом вызове конструктора у нас фактически уже есть нужный объект. И потом без виртуальности этого не происходит, т. е. конструктор для (C) вызывается 1 раз, значит в принципе конструктор копирования не нужен здесь, это ведь не не инициализация от готового объекта по сути, это просто инициализация через вызов конструктора. Что такого есть в виртуальности, что компилятор генерирует вызов ещё и конструктора копирования?

Добавлено через 5 минут
Цитата Сообщение от alsav22 Посмотреть сообщение
Что в этом странного? Первый раз просто конструктор: C(A()), второй раз конструктор копирования, для инициализации этим, созданным объектом, объекта c
Зачем это нужно, если можно вызвать конструктор (не копирования) сразу для (С)?

Добавлено через 1 минуту
Цитата Сообщение от Cra3y Посмотреть сообщение
C++
1
2
3
4
5
6
// код
C c = C(A());
// равносилен
A a;
C temp(a);
C c(temp);
Если бы было так, то без виртуальности вывод на левом скриншоте и правом совпадали бы. Тут ключевой момент именно в виртуальности. Без неё конструктор копирования не вызывается.

Добавлено через 2 минуты
И если передавать класс (A) по ссылке, то и с виртуальностью, и без виртуальности конструктор копирования не вызывается. Значит всё-таки код
C++
1
C c = C(A());
и
C++
1
2
3
A a;
C temp(a);
C c(temp);
не равносильны.
0
46 / 46 / 18
Регистрация: 25.10.2011
Сообщений: 183
28.10.2013, 15:14
Так зачем писать было
C++
1
C c = C(A());
Что бы работало, как я написал:
C++
1
C c(A());
Или я чего-то не понимаю в вашем вопросе?
0
 Аватар для Виктор_Сен
36 / 29 / 2
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 15:20  [ТС]
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
#include <iostream>
using namespace std;
 
class A
{
public:
    A(){cout<<"A()"<<endl;}
    virtual ~A(){cout<<"~A()"<<endl;}
};
 
class C
{
public:
    C(A& a){cout<<"C(A())"<<endl;}
    ~C(){cout<<"~C()"<<endl;}
    C(C& c){cout<<"C(C& c)"<<endl;}
};
 
int main()
{
    C c=C(A());
 
    system("pause");
    return 0;
}
Такой код например уже даёт вывод
A()
C(A())
~A()

Добавлено через 2 минуты
Цитата Сообщение от Hunter13ua Посмотреть сообщение
Что бы работало, как я написал:
Код C++
1
C c(A());
Так вообще ни какого вывода нет, т. к. вот что:
Предупреждение 1 warning C4930: C c(A (__cdecl *)(void)): функция с прототипом не вызвана (предполагалось определение переменной?) D:\documents\Visual Studio 2010\Projects\LSD\LSD\main.cpp 26 1 LSD
0
205 / 165 / 41
Регистрация: 25.10.2013
Сообщений: 527
28.10.2013, 15:22
Вам для полного понимания, надо было бы ещё в A указать ещё конструктор копирования, а то используется конструктор по умолчанию, который ничего не выводит.
0
 Аватар для Виктор_Сен
36 / 29 / 2
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 15:25  [ТС]
Цитата Сообщение от Hunter13ua Посмотреть сообщение
Или я чего-то не понимаю в вашем вопросе?
Всё-таки при определении переменной нужен знак равенства, и при определении переменной, как я понимаю, этот знак равенства эквивалентен не копированию, а созданию "с нуля" переменной, если справа от знака равенства нет уже существующей переменной (которая связана с буквой, её обозначающей).
0
Диванный эксперт
Эксперт С++
 Аватар для Max Dark
2550 / 2064 / 971
Регистрация: 09.10.2013
Сообщений: 4,793
Записей в блоге: 4
28.10.2013, 15:28
У меня это не компилится %)
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
max@notebook:~/src/tests$ g++ c.cpp
c.cpp: In function ‘int main()’:
c.cpp:21:16: error: no matching function for call to ‘C::C(A)’
     C c = C(A());
                ^
c.cpp:21:16: note: candidates are:
c.cpp:16:5: note: C::C(C&)
     C(C& c){ cout << "C(C &c)" << endl;}
     ^
c.cpp:16:5: note:   no known conversion for argument 1 from ‘A’ to ‘C&’
c.cpp:14:5: note: C::C(A&)
     C(A &a){cout << "C(A a)" << endl;}
     ^
c.cpp:14:5: note:   no known conversion for argument 1 from ‘A’ to ‘A&’
max@notebook:~/src/tests$ g++ --version
g++ (Ubuntu/Linaro 4.8.1-10ubuntu8) 4.8.1
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.10.2013, 15:35
C++
1
C c=C(A());
Есть инициализировать объект C объектом, получившемся из использования C(A()), используя конструктор копирования (или не используя, зависит от copy-elision).
Без конструктора копирования нужно:
C++
1
C c((A()));
Ну и да, код не скомпилируется, т.к. на временную переменную нельзя создать ссылку (скомпилируется только в студии).
0
 Аватар для Виктор_Сен
36 / 29 / 2
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 15:35  [ТС]
У меня нормально компилится
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
#include <iostream>
using namespace std;
 
class A
{
public:
    A(){cout<<"A()"<<endl;}
    virtual ~A(){cout<<"~A()"<<endl;}
    A(A& a){cout<<"A(A& a)"<<endl;}
};
 
class C
{
public:
    C(A a){cout<<"C(A())"<<endl;}
    ~C(){cout<<"~C()"<<endl;}
    C(C& c){cout<<"C(C& c)"<<endl;}
};
 
int main()
{
    C c=C(A());
 
    system("pause");
    return 0;
}
Вот вывод
Миниатюры
При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О  
0
5499 / 4894 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
28.10.2013, 15:36
Цитата Сообщение от Виктор_Сен Посмотреть сообщение
Получается, что создаётся временный объект C(A())), потом от него инициализируется уже (c). Вот я и не понимаю, зачем это нужно, если при первом вызове конструктора объект уже есть...
Потому что код так написан. Спросите у того, кто его писал, зачем он так сделал.
0
 Аватар для Виктор_Сен
36 / 29 / 2
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 15:38  [ТС]
Цитата Сообщение от ForEveR Посмотреть сообщение
Без конструктора копирования нужно:
Код C++
1
C c((A()));
Так у меня вообще ни какой конструктор не вызывается. И варинг появляется:
Предупреждение 1 warning C4930: C c(A (__cdecl *)(void)): функция с прототипом не вызвана (предполагалось определение переменной?) D:\documents\Visual Studio 2010\Projects\LSD\LSD\main.cpp 27 1 LSD

Добавлено через 1 минуту
Цитата Сообщение от alsav22 Посмотреть сообщение
Потому что код так написан. Спросите у того, кто его писал, зачем он так сделал.
А по-другом вообще конструктор не вызывается.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.10.2013, 15:39
Виктор_Сен, На скобки смотрите внимательнее. Точнее на кол-во скобок.
1
 Аватар для Виктор_Сен
36 / 29 / 2
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 15:42  [ТС]
Но без виртуальности вызова конструктора копирования нет. В этом видимо причина.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.10.2013, 15:42
А вообще вот, почитайте: Как работает компилятор при создании объекта недавно была тема именно про это.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
28.10.2013, 15:42
Помогаю со студенческими работами здесь

Виртуальный деструктор вызывается два раза
Здравствуйте, у меня есть базовый и производный классы с динамическими массивами, я создаю массив указателей на базовый класс пытаюсь...

Почему деструктор вызывается два раза
Всем привет. Есть код, для примера #include &lt;vector&gt; using namespace std; struct AA { int n; AA() :n(0) { cout &lt;&lt;...

Конструктор вызывается 2 раза
Помогите пожалуйста найти ошибку. Конструктор вызывается 2 раза. #include &lt;iostream&gt; #include &lt;stdio.h&gt; #include...

Когда вызывается деструктор класса?
Вопрос собственно в том, когда происходит освобождение памяти, занимаемой объектом класса? Допустим имеем #include &lt;iostream&gt; ...

При динамическом создании объекта в классе деструктор не вызывается
Добрый день еще раз. Помогите заполнить пробелы в ООП) Есть три класса: // Вспомогательный класс class Object { public: ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru