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

Почему не вызывается конструктор копирования? - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 30, средняя оценка - 4.83
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,265
05.11.2010, 21:40     Почему не вызывается конструктор копирования? #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
#include <iostream>
using namespace std;
 
class baze {
public:
 
 //Конструктр объекта класса baze, заданный по умолчанию
 baze () {printf ("wwwww\n");};
 
 //Эта функция, которая принимает ссыочный аргумент. Следовательно, при её вызове ДОЛЖЕН 
 //вызваться конструктр копирования
 void funktsia(const baze &other){
  printf ("lllll\n");
 }
 
 //А вот и сам конструктр копирования. Он иногда должен вызываться. Где- см. ниже 
 baze (const baze &src) {
  printf ("rrrrr\n");
 }
 
};
 
int main() {
 
 baze f;
 
 //В это месте должен вызываться конструктор копирования, ибо функция funktsia() принимает
 //ссылочный аргумент. Тычем на исполнение и ждём появления строчки "rrrrr"
 f.funktsia(f);
 
 //Но наблюдаем всего лишь "wwwww" (создался объект класса baze) и "lllll" (вызвана функция
 //funktsia () Как она приняла аргумент- для меня до сих пор загадка.)
 //Конструктор копирования не вызван. ПОчему?
 getchar ();
 return 0;
}
Добавлено через 2 минуты
Спасибо заранее
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.11.2010, 21:40     Почему не вызывается конструктор копирования?
Посмотрите здесь:

Сколько раз вызывается конструктор копирования C++
Будет ли утрачена память, когда конструктор копирования вызывается для уже существующего объекта класса? C++
Почему конструктор вызывается повторно при преобразовании типов? C++
Когда вызывается конструктор копирования? C++
Почему не вызывается конструктор копии? C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
05.11.2010, 21:52     Почему не вызывается конструктор копирования? #2
Если принимается ссылочный аргумент, то конструктор копирования НЕ вызывается!

Добавлено через 1 минуту
вот так вызовется
C++
1
2
3
void funktsia( baze other){
  printf ("lllll\n");
 }
Unforgiven_00
60 / 60 / 2
Регистрация: 12.10.2010
Сообщений: 129
05.11.2010, 21:53     Почему не вызывается конструктор копирования? #3
Если в функцию передавать не ссылку, а обьект, тогда и будет использоваться конструктор копирования, а как раз з ссылкой этого не будет происходить.
C++
1
2
3
 void funktsia(const baze other){
  printf ("lllll\n");
 }
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,265
05.11.2010, 22:17  [ТС]     Почему не вызывается конструктор копирования? #4
Стоп-стоп. Ребята, в этой же книге определён синтаксис конструктора копирования, а вы оба от него отошли. Синтаксис такой: (дословно)

"Синтаксис для объявления конструктора копирования следующий:
имя_класса (имя_класса const & источник)"

То есть надо именно так.

Unforgiven_00,
я Вам больше скажу, в книжке написано, что ваш вариант исползовать нельзя и даже описано почему нельзя. ПОка не буду на этом заострять внимания (если чё после аргументирую)

Итак, вопрос остаётся открытым
Unforgiven_00
60 / 60 / 2
Регистрация: 12.10.2010
Сообщений: 129
05.11.2010, 22:22     Почему не вызывается конструктор копирования? #5
ДА, const лучше убрать, я тоже не буду заострять внимания.
C++
1
2
3
void funktsia(baze other){
  printf ("lllll\n");
 }
Теперь по сабжу. Конструктор копирования никто не изменял. Изменили только функцию.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,265
05.11.2010, 22:34  [ТС]     Почему не вызывается конструктор копирования? #6
Ну да.
Надо закреплять всё это. Спасибо.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,265
11.05.2011, 23:00  [ТС]     Почему не вызывается конструктор копирования? #7
ОК, с одним разобрались, а теперь вот другая ситуация; тоже должен вызываться конструктор копирования и тоже он не вызывается. Почему? Хотя в книге написано, что конструктор копирования вызывается, когда возвращаемое значение имеет тип класса!
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
#include <iostream>
using namespace std;
 
class arr
{
  public:
    arr(int number){};
    arr(const arr &obj);
};
 
 
arr::arr(const arr &obj)
{
  cout << "Вызов копирующего конструктора" << "\n";
}
 
 
arr get_object (int number) {
 arr obj (number);
 return obj; 
}
 
 
 
 
int main()
{
  //Функция get_object должна вернуть объект, но она НЕ ВОЗВРАЩАЕТ! Почему?
  get_object(15);
  getchar ();
  return 0;
}
asics
Freelance
Эксперт C++
 Аватар для asics
2838 / 1775 / 144
Регистрация: 09.09.2010
Сообщений: 3,842
11.05.2011, 23:21     Почему не вызывается конструктор копирования? #8
Цитата Сообщение от kravam Посмотреть сообщение
//Функция get_object должна вернуть объект, но она НЕ ВОЗВРАЩАЕТ! Почему?
Потому что вы возвращаете локальный обект, добавьте ключевое слово static и конструктор копии вызоветься.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,265
11.05.2011, 23:27  [ТС]     Почему не вызывается конструктор копирования? #9
А куда добавить static?
asics
Freelance
Эксперт C++
 Аватар для asics
2838 / 1775 / 144
Регистрация: 09.09.2010
Сообщений: 3,842
11.05.2011, 23:29     Почему не вызывается конструктор копирования? #10
19 строка.
Нач_физик
2 / 2 / 0
Регистрация: 12.02.2011
Сообщений: 49
11.05.2011, 23:33     Почему не вызывается конструктор копирования? #11
А откуда знаете, что не возвращает? Как проверить то вернул объект или нет, по коду не видно как?
Конструктор отрабатывает и всё больше ни каких сообщений не предусмотренно.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,265
11.05.2011, 23:44  [ТС]     Почему не вызывается конструктор копирования? #12
Цитата Сообщение от Нач_физик Посмотреть сообщение
А откуда знаете, что не возвращает? Как проверить то вернул объект или нет, по коду не видно как?
Конструктор отрабатывает и всё больше ни каких сообщений не предусмотренно.
Как это не предусмотрено? Очень даже предусмотрено

C++
1
cout << "Вызов копирующего конструктора" << "\n";
//+++++++++++++++++++++++++++++++++++++++++++++++++
static это static, а вот как без static? Да и мне непонятно, почему без static не вызывается конструктор
копирования? Ну и что, что объект локальный, функции и должны возвращать значения ЛОКАЛЬНЫХ
переменных (Не глобальных же). Кстати, это происходит сплошь и рядом
C++
1
2
3
4
5
6
7
char* f () {
 char p []= "stroka";
 return p;
} 
 
int main () {
}
Я специально привёл этот код, чтобы предупредить возможные возражения.
Да, могут выдаться разные предупреждения, особенно если p инициализировано локальной же строкой. Но факт остаётся фактом- значение p- адреса локальной переменной возвернётся (предврительно скопировавшись... Ну если уж кому интересно в регистр EAX. В общем, ВО ВНЕ. И заметтье, безо всяких static!). А там уж на усмотрение программиста, что он будет с этим значение делать.

А локальные объекты не возвращаются/не копируются. Странно
SashaPinsk
 Аватар для SashaPinsk
39 / 37 / 2
Регистрация: 27.12.2009
Сообщений: 73
12.05.2011, 00:28     Почему не вызывается конструктор копирования? #13
Конструктор копирования в твоём коде вызывается. Почему ты решил, что он не вызывается?

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
#include <iostream>
#include <locale>
 
using namespace std;
 
class arr
{
  public:
    arr(int number){};
    arr(const arr &obj);
};
 
 
arr::arr(const arr &obj)
{
  cout << "Вызов копирующего конструктора" << "\n";
}
 
 
arr get_object (int number) {
 arr obj (number);
 return obj; 
}
 
 
 
 
int main()
{
    setlocale(LC_ALL, "Russian");
    //Функция get_object должна вернуть объект, но она НЕ ВОЗВРАЩАЕТ! Почему?
    get_object(15);
    getchar ();
    return 0;
}
Нач_физик
2 / 2 / 0
Регистрация: 12.02.2011
Сообщений: 49
12.05.2011, 07:02     Почему не вызывается конструктор копирования? #14
Ну, и я говорю конструктор копирования отрабатывает, стороку выводит.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
12.05.2011, 08:58     Почему не вызывается конструктор копирования? #15
Не путайте теорию с практикой. В книге написано одно, а оптимизирующий компилятор делает другое. Если можно безболезненно удрать копирование, оно будет убрано. Если можно вызов функции убрать, она будет убрана.

Цитата Сообщение от kravam Посмотреть сообщение
Я специально привёл этот код, чтобы предупредить возможные возражения.
char* f () { char p []= "stroka"; return p; }
А это вообще некорректный код и делать так нельзя.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,265
12.05.2011, 10:14  [ТС]     Почему не вызывается конструктор копирования? #16
Цитата Сообщение от SashaPinsk Посмотреть сообщение
Конструктор копирования в твоём коде вызывается. Почему ты решил, что он не вызывается?
потому, что я не вижу этой строки; проверено.
C++
1
cout << "Вызов копирующего конструктора" << "\n";
Также он не вызывается если:
C++
1
arr x= get_object(15);
, то есть x создаётся корректно, (для объекта arr я вводил приватный член и в конструкторе
присваивал ему значение
аргумента (в данном случае 15), а потом выводил его; выводилось без
ошибок)

Добавлено через 2 минуты
Цитата Сообщение от Deviaphan Посмотреть сообщение
Не путайте теорию с практикой. В книге написано одно, а оптимизирующий компилятор делает другое. Если можно безболезненно удрать копирование, оно будет убрано. Если можно вызов функции убрать, она будет убрана.
Ну, короче, всё плохо. Ты пыхтишь, переопределяешь конструкторы, ждёшь их вызов. А они не вызываются. И вся программа крахом.
...И даже если ты её подгонишь по капризы отдельного компилятора, под все компиляторы её не подогнать.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
12.05.2011, 10:47     Почему не вызывается конструктор копирования? #17
Цитата Сообщение от kravam Посмотреть сообщение
Ну, короче, всё плохо.
Нет! Всё хорошо!
В 99.9% случаев, конструктор копирования создаёт точную копию копируемого объекта. Оптимизирующий компилятор убирает создание временного объекта, оставляя результирующий, т.е. ты получаешь код с точно тем же функционалом, но без создания временного объекта. Т.е. меньше и по размеру и по времени выполнения. В ситуациях, когда конструктор копирования должен быть вызван, он будет вызван. Не переживай.

Добавлено через 3 минуты
В данном коде конструктор копирования будет вызываться. Компилятор ничего не поделает, т.к. у разных объектов должны быть разные адреса.
C++
1
2
3
4
arr A(5);
arr B( A );
// Используем А и В, чтобы их не удалил оптимизатор
cout << &A << &B;
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,265
12.05.2011, 11:04  [ТС]     Почему не вызывается конструктор копирования? #18
Речь не об экономии ресурсов на создании временного объекта- этот мне как раз понятно, что да, экономия. Но! Я переопределяю конструктор копирования, внедряю туда ВАЖНЫЙ код, а компилятор не вызывает его и код не выполняется.

А это болезненно. И даже очень болезненно. И даже очень-очень болезненно.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
12.05.2011, 11:28     Почему не вызывается конструктор копирования? #19
Цитата Сообщение от kravam Посмотреть сообщение
А это болезненно. И даже очень болезненно. И даже очень-очень болезненно.
Ты не прав. Компилятору понятно, что ты не прав, а тебе нет.)
Копирование - создание дубликата. Т.е. между ручным созданием двух одинаковых объектов и копированием второго из первого нет никакой разницы (в 99.9% случаев, но у тебя не тот 0.1%).
Компилятор видит, что первый объект создаётся только для инициализации второго, поэтому он его удаляет и инициализирует сразу второй объект. Всё корректно.
Если тебе уж очень хочется совпадения с теорией, то отключи в настройках проекта все оптимизации. А лучше в дебаге играйся, потрейсить сможешь.

Или сделай глобальную переменную и инкрементируй её значение в конструкторах. Возможно, компилятор не догадается, как такой код оптимизировать.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.05.2011, 12:15     Почему не вызывается конструктор копирования?
Еще ссылки по теме:

C++ В каких случаях вызывается конструктор копирования, и стоит ли вообще об этом думать?
Почему конструктор вызывается при присвоении объекта другому объекту C++
C++ Почему не вызывается конструктор копирования при возврате объекта из функции

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

Или воспользуйтесь поиском по форуму:
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,265
12.05.2011, 12:15  [ТС]     Почему не вызывается конструктор копирования? #20
ОК, а тогда для чего вообще придумана такая штука, как создание собственных конструкторов копирования? Если встроенный с успехом справляется с возложенной на него задачей? Вот одна из ситуаций:если один из членов объекта X будет указывать допустим, на строку. И вот: я пишу конструктор копирования, который создаёт объект Y с указателем на новую строку с тем же содержанием, что и в копируемом объекте (применяю посимвольное копирование строк).

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
#include <iostream>
#include <locale>
 
using namespace std;
class arr {
  public:
    arr(){p= new char [7]; strcpy (p, "stroka");};
    arr(const arr &obj);
    ~arr(){delete p;}
  private:
    char* p;          
};
 
 
//Вот в этом конструкторе строка копируется посимвольно
arr::arr(const arr &obj){
 p= new char [7];
 strcpy (p, obj.p);
 cout << "Вызов копирующего конструктора" << "\n";
}
 
 
//А вот по возвращении из этой функции и должен будет ызваться МОЙ конструктор копирования
//Но он не вызовется  
arr get_object () {
 arr obj;
 return obj; 
}
 
 
 
 
int main(){
 
  arr x= get_object();
  //А теперь мы имеем, что x.p указывает на строку, КОТОРОЙ НЕТ, ибо
  //для указателя, который на неё указывал, была выполнена операция:
  //delete p (по выходе из функции get_object обюъект obj был разрушен и был вызван его деструктор)         
  
  getchar ();
  return 0;
}
Всё, приехали. И такая ситуация как раз очень-очень часта; в том учебнике, где будет описано написание конструкторов копирования, считай, что там будет описана такая же ситуация. И это не 1%, согласись?
...И при её возникновении будет крах. То ли компилятор вставит то ли нет консруктор копирования.
А по опциям- у меня все опции отключены; да и простая компиляция из командной строки

C++
1
g++ main.cpp
приводит к результату невызывания моего конструктора копирования.

Добавлено через 3 минуты
Вообще любой АВТОРСКИЙ конструктор копирования (что бы он не делал) подразумевает отход от просто посимвольного копирования байтов, а некоторый СВОЙ код, которой не выполнится.
Yandex
Объявления
12.05.2011, 12:15     Почему не вызывается конструктор копирования?
Ответ Создать тему
Опции темы

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