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

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

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.78
Виктор_Сен
 Аватар для Виктор_Сен
30 / 23 / 1
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 14:18     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #1
Вот такой код
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 раза, затем вызывается деструктор о_О  
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.10.2013, 14:18     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О
Посмотрите здесь:

C++ Не вызывается конструктор базового класса
Два раза вызывается деструктор C++
Не вызывается нужный конструктор базового класса C++
Когда вызывается деструктор класса? C++
this(Всегда ли вызывается конструктор при не явной передачи объекта в конструктор) C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
28.10.2013, 14:41     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #2
Цитата Сообщение от Виктор_Сен Посмотреть сообщение
Но ни могу понять почему именно конструктор C().
При инициализации объекта (с) другим объектом (созданным с помощью C(A())), вызывается конструктор копирования.
Hunter13ua
46 / 46 / 5
Регистрация: 25.10.2011
Сообщений: 183
28.10.2013, 14:43     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #3
1. Вызывается конструктор А
2. Вызывается конструктор копий С
3. Вызывается деструктор А
Что странного?
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
28.10.2013, 14:51     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #4
С виртуальностью - 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 раза, затем вызывается деструктор о_О  
Виктор_Сен
 Аватар для Виктор_Сен
30 / 23 / 1
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 14:51  [ТС]     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #5
Цитата Сообщение от Hunter13ua Посмотреть сообщение
1. Вызывается конструктор А
2. Вызывается конструктор копий С
3. Вызывается деструктор А
Что странного?
То, что Вы написали, НЕ странно. Странно то, что вызывается 2 раза конструктор для объекта C. На левом скриншоте это выделено
Assembler
1
2
3
4
5
6
call C::C
...
call C::C
...
call C::~C
...
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
28.10.2013, 14:55     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #6
Цитата Сообщение от Виктор_Сен Посмотреть сообщение
Странно то, что вызывается 2 раза конструктор для объекта C.
Что в этом странного? Первый раз просто конструктор: C(A()), второй раз конструктор копирования, для инициализации этим, созданным объектом, объекта c.
Миниатюры
При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О  
Max Dark
В поиске работы
 Аватар для Max Dark
1546 / 1399 / 501
Регистрация: 09.10.2013
Сообщений: 3,185
Записей в блоге: 8
Завершенные тесты: 2
28.10.2013, 15:02     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #7
C++
1
2
3
4
5
6
// код
C c = C(A());
// равносилен
A a;
C temp(a);
C c(temp);
Виктор_Сен
 Аватар для Виктор_Сен
30 / 23 / 1
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 15:14  [ТС]     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #8
Цитата Сообщение от 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);
не равносильны.
Hunter13ua
46 / 46 / 5
Регистрация: 25.10.2011
Сообщений: 183
28.10.2013, 15:14     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #9
Так зачем писать было
C++
1
C c = C(A());
Что бы работало, как я написал:
C++
1
C c(A());
Или я чего-то не понимаю в вашем вопросе?
Виктор_Сен
 Аватар для Виктор_Сен
30 / 23 / 1
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 15:20  [ТС]     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #10
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
Shtirliz72
200 / 160 / 38
Регистрация: 25.10.2013
Сообщений: 527
28.10.2013, 15:22     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #11
Вам для полного понимания, надо было бы ещё в A указать ещё конструктор копирования, а то используется конструктор по умолчанию, который ничего не выводит.
Виктор_Сен
 Аватар для Виктор_Сен
30 / 23 / 1
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 15:25  [ТС]     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #12
Цитата Сообщение от Hunter13ua Посмотреть сообщение
Или я чего-то не понимаю в вашем вопросе?
Всё-таки при определении переменной нужен знак равенства, и при определении переменной, как я понимаю, этот знак равенства эквивалентен не копированию, а созданию "с нуля" переменной, если справа от знака равенства нет уже существующей переменной (которая связана с буквой, её обозначающей).
Max Dark
В поиске работы
 Аватар для Max Dark
1546 / 1399 / 501
Регистрация: 09.10.2013
Сообщений: 3,185
Записей в блоге: 8
Завершенные тесты: 2
28.10.2013, 15:28     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #13
У меня это не компилится %)
Код
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
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.10.2013, 15:35     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #14
C++
1
C c=C(A());
Есть инициализировать объект C объектом, получившемся из использования C(A()), используя конструктор копирования (или не используя, зависит от copy-elision).
Без конструктора копирования нужно:
C++
1
C c((A()));
Ну и да, код не скомпилируется, т.к. на временную переменную нельзя создать ссылку (скомпилируется только в студии).
Виктор_Сен
 Аватар для Виктор_Сен
30 / 23 / 1
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 15:35  [ТС]     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #15
У меня нормально компилится
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 раза, затем вызывается деструктор о_О  
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
28.10.2013, 15:36     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #16
Цитата Сообщение от Виктор_Сен Посмотреть сообщение
Получается, что создаётся временный объект C(A())), потом от него инициализируется уже (c). Вот я и не понимаю, зачем это нужно, если при первом вызове конструктора объект уже есть...
Потому что код так написан. Спросите у того, кто его писал, зачем он так сделал.
Виктор_Сен
 Аватар для Виктор_Сен
30 / 23 / 1
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 15:38  [ТС]     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #17
Цитата Сообщение от 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 Посмотреть сообщение
Потому что код так написан. Спросите у того, кто его писал, зачем он так сделал.
А по-другом вообще конструктор не вызывается.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.10.2013, 15:39     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #18
Виктор_Сен, На скобки смотрите внимательнее. Точнее на кол-во скобок.
Виктор_Сен
 Аватар для Виктор_Сен
30 / 23 / 1
Регистрация: 01.08.2011
Сообщений: 176
28.10.2013, 15:42  [ТС]     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #19
Но без виртуальности вызова конструктора копирования нет. В этом видимо причина.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.10.2013, 15:42     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О
Еще ссылки по теме:

Конструктор вызывается один раз, а деструктор два раза C++
Не вызывается деструктор при работе с классом C++
Конструктор вызывается 2 раза C++

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

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.10.2013, 15:42     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О #20
А вообще вот, почитайте: Как работает компилятор при создании объекта недавно была тема именно про это.
Yandex
Объявления
28.10.2013, 15:42     При создании класса конструктор вызывается 2 раза, затем вызывается деструктор о_О
Ответ Создать тему
Опции темы

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