Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.71
AnreyKazakov
Заблокирован
#1

Что такое конструктор копий? - C++

02.10.2012, 00:13. Просмотров 2923. Ответов 22
Метки нет (Все метки)

Объясните, пожалуйста, на максимально простом языке, чем отличается конструктор от конструктора копий?
Может это и одно и то же, хотя вряд ли, в книжке в разных разделах инфа выложена...
под конструктором я понимаю что-то вроде:
C++
1
2
3
4
class as{
as():a(155){}
int a;
};
Если класс объявлен, а переменная а не инициализирована, то значение а 155.
А что такое конструктор копий? Злость берет, что нифига не понимаю.... Единственное порадовало: "Зачастую самой трудной задачей при определении конструктора копий является собственно осознание того,что он необходим"
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.10.2012, 00:13
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Что такое конструктор копий? (C++):

Что такое конструктор? - C++
Конструктор - это такие детали , как map , player, enemy.Я правильно понял?

что такое конструктор? - C++
Обьясните плиз что такое конструктор? Это функция а что она делает и для чего?

Конструктор копий - C++
Добрый день, изучая работу со списками и классы, дошел до такой проблемы: Нужно было создать односвязный список и продлить его же...

Конструктор копий - C++
Можно ли вызвать в конструкторе копий, конструктор, если объекту нечего передавать? Класс - абстрактный. В конструкторе идет подсчет...

Конструктор копий - C++
Добрый день! Пытаюсь разобраться с конструктором копий, а именно: когда его использовать и как реализовать. С первым, вроде как,...

Что такое конструктор по умолчанию? Как инициализируются данные-члены объекта? - C++
Что такое конструктор по умолчанию? Как инициализируются элементы данных объекта, если класс имеет только неявно определенный...

22
John Prick
821 / 754 / 152
Регистрация: 27.07.2012
Сообщений: 2,147
Завершенные тесты: 3
02.10.2012, 00:21 #2
Конструктор копий - это чей-то гуглоперевод. Правильнее называть эту штуку - копирующий конструктор. Этот конструктор при создании элемента принимает в качестве единственного параметра объект того же типа, который и создаётся, делая копию необходимой информации из объекта-аргумента конструктора в создаваемый объект.
Кусочек кода:
C++
1
2
3
4
5
6
7
class CA
{
   int a;
public:
   CA() : a(0) {}                      // просто конструктор (конструктор по умолчанию)
   CA(CA & Copy) : a(Copy.a) {}  // копирующий конструктор, копирует Copy в создаваемый объект
};
2
AnreyKazakov
Заблокирован
02.10.2012, 00:31  [ТС] #3
C++
1
2
3
4
5
6
7
class CA
{
   int a;int b;
public:
   CA() : a(0),b(0) {}                      // просто конструктор (конструктор по умолчанию)
   CA(CA & Copy) : a(Copy.a),b(Copy.b) {}  // копирующий конструктор, копирует Copy в создаваемый объект
};
Если будет два значения, а и б, я правильно копирующий конструктор описал?
Да и вопрос, он нужен вообще? Просто в книжке мало описывается сам конструктор, но зато оч много о том, что по умолчанию ВСЕГДА, он есть....И еще правильна ли будет такая запись? Если я хочу в обе переменные нового объекта класса записать значения а.
C++
1
2
3
4
5
6
7
class CA
{
   int a;int b;
public:
   CA() : a(0),b(0) {}                      // просто конструктор (конструктор по умолчанию)
   CA(CA & Copy) : a(Copy.a),b(Copy.a) {}  // копирующий конструктор, копирует Copy в создаваемый объект
};
0
Sher_vud
4 / 4 / 1
Регистрация: 25.09.2012
Сообщений: 42
02.10.2012, 00:53 #4
тоже столкнулся с проблемой запуска конструктора копирования, изучая пример из учебника. листинг следующий:
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <cstring>
using namespace std;
////////////////////////////////////////////////////////////////////////////////
class strCount
{
      private:
              int count;
              char *str;
              friend class String;
      public:
             strCount(char *s)
             {
                           int length = strlen(s);
                           str = new char [length+1];
                           strcpy(str, s);
                           count = 1;
                           }
             ~strCount()
             { delete [] str; }
};
////////////////////////////////////////////////////////////////////////////////
class String
{
      private:
              strCount *ptr;
      public:
             String()
             {
                     ptr = new strCount("NULL");
                     }
             String(char *t)
             {
                     ptr = new strCount(t);
                     }
             String(const String &T)    //если не проставить "const" компилятор выдает ошибку
             {                                              // при этом в исходном примере const  не стоит 
                     cout << "\nkopirovanie\n";
                     ptr = T.ptr;
                     (ptr -> count)++;
                     }
             ~String()
             {
                      if(ptr->count == 1)
                      delete ptr;
                      else
                      (ptr->count)--;
                      }
             void display()
             {
                  cout << endl << ptr->str;
                  cout << " addr " << ptr;
                  }
             String& operator = (String& T)
             {
                     cout << "\nprisvaivanie\n";
                     if(ptr->count==1)
                     delete ptr;
                     else
                     (ptr->count)--;
                     ptr = T.ptr;
                     (ptr->count)++;
                     return *this;
                     }
};
////////////////////////////////////////////////////////////////////////////////
int main()
{
    String ss1 = "test test";
    String ss2, ss3;
    ss3 = ss2 = ss1;
    ss1.display();
    ss2.display();
    ss3.display();
    cout << endl;
    system("pause");
    return 0;
}
при запуске так же не появляется сообщения, за которое отвечает строчка:
cout << "\nkopirovanie\n";
и становится теперь совсем не понятно, запускается ли мой конструктор копирования или конструктор копирования по умолчанию
если кто знает подскажите пожалуста

хмм похоже все таки в данном случае конструктор копирования по умолчанию
добавил сейчас объект ss4 и проинициализировал его значением ss1, после чего вывел. появилось сообщение запуска моего конструктора копирования:
что добавил:
C++
1
2
String ss4 = ss1;
ss4.display();
я в сметении, почему же происходит именно так??
0
alsav22
5428 / 4823 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
02.10.2012, 06:05 #5
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Sher_vud Посмотреть сообщение
я в сметении, почему же происходит именно так??
Читайте о конструкторе копирования и поймёте. В вашем коде он и не дожен был вызываться. Создаётся новый объект и инициализируется существующим объектом такого же типа - вот один из случаев, когда вызывается конструктор копирования. Именно при создании объекта. Другой случай, когда объект или передаётся в функцию по значению, или возвращается из функции. Тут тоже создаются копии конструктором копирования. Компилятор использует конструктор копирования, также, и для создания временных объектов, например, для хранения промежуточных результатов вычислений.

Добавлено через 50 минут
Цитата Сообщение от AnreyKazakov Посмотреть сообщение
Да и вопрос, он нужен вообще?
В ваших примерах достаточно конструктора копирования по умолчанию, потому что он сделает то же самое, что и вы прописали делать своему конструктору копирования, а именно: поэлементное копирование полей класса. Свой конструктор копирования нужен, если, например, у вас в полях класса используются указатели. Например:
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
class 
CA
{
   int *a;
   int *b;
public:
   CA() 
  {
      a = new int(0);
      b = new int(0);
   }                     
   
   ~CA()
   {
         delete a;
         delete b;
   }
};
 
int main()
{
    CA k;
    CA m = k; // вызывается конструктор копирования по умолчанию
 
    return 0;
}
В данном случае конструктор копирования по умолчанию просто скопирует указатели, а не то, на что они указывают (поверхностное копирование). В результате, указатели объектов k и m будут указывать на одну и ту же область динамической памяти. При уничтожении объектов вызовется деструктор и будет попытка освобождения уже свободной памяти, что вызовет ошибку. Чтобы этого избежать, нужно определить свой конструктор копирования, который будет делать, так называемое, глубокое копирование.
C++
1
2
3
4
5
CA(const CA &Copy) // конструктор глубокого копирования
   {
        a = new int(*Copy.a);
        b = new int(*Copy.b); 
   }
Теперь у каждого объекта будет своя копия данных. Всё сказанное относится и к оператору присваивания, который тоже есть по умолчанию.
3
John Prick
821 / 754 / 152
Регистрация: 27.07.2012
Сообщений: 2,147
Завершенные тесты: 3
02.10.2012, 11:03 #6
Цитата Сообщение от AnreyKazakov Посмотреть сообщение
Если будет два значения, а и б, я правильно копирующий конструктор описал?
Правильно.

Цитата Сообщение от AnreyKazakov Посмотреть сообщение
Да и вопрос, он нужен вообще? Просто в книжке мало описывается сам конструктор, но зато оч много о том, что по умолчанию ВСЕГДА, он есть....
Если копирующий конструктор явно не объявить в классе, то компилятор сгенерирует его автоматически. Как уже писали выше, не всегда компилятор сделает то, что нужно нам, поэтому в этих случаях копирующий конструктор объявляют явно. Однако это не единственный случай, когда бывает нужно явно объявить копирующий конструктор. Мы, например, можем захотеть запретить копирование объектов данного класса. Тогда мы объявляем копирующий конструктор в закрытой области:
C++
1
2
3
4
5
class T
{
private:
   T(const T&) {}
};
Цитата Сообщение от AnreyKazakov Посмотреть сообщение
И еще правильна ли будет такая запись? Если я хочу в обе переменные нового объекта класса записать значения а.
Ну если вам оно так надо по задаче, то можно и так сделать. Я, правда, не могу так сходу придумать, когда такое бывает нужно. Можно инициализировать поля копии какими-то начальными значениями, а не значениями этих же полей исходного объекта (например, если в классе есть какие-то счётчики или что-то подобное).

Добавлено через 2 минуты
Цитата Сообщение от Sher_vud Посмотреть сообщение
и становится теперь совсем не понятно, запускается ли мой конструктор копирования или конструктор копирования по умолчанию
Как уже писал, если в классе объявлен копирующий конструктор, то копирующего конструктора по умолчанию в нём уже нет. Короче, в классе может быть только один копирующий конструктор. В вашем коде копирующий конструктор в принципе не вызывается.
2
taras atavin
3570 / 1754 / 91
Регистрация: 24.11.2009
Сообщений: 27,567
02.10.2012, 11:08 #7
Есть копирующий оператор присваивания, он превращает один уже существующий объект в точную копию другого, а есть копирующий конструктор, он создаёт копию в новом объекте.
0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
02.10.2012, 11:14 #8
alsav22,
John Prick,
C++
1
String ss1 = "test test";
Инициализация копированием. При проверке эквивалентно
C++
1
String ss1 = String("test test");
Компилятор ОБЯЗАН проверить, что есть подходящий копирующий конструктор, а будет-ли вызван или нет зависит от компилятора и опций.
1
novi4ok
551 / 504 / 8
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
02.10.2012, 11:44 #9
AndreyKazakov, объясняю на пальцах. если у тебя есть некий класс ClassX, и ты напишешь:
C++
1
2
3
4
ClassX x0;
// здесь ты делаешь что-то с классом x0, а затем пишешь:
ClassX x1;
x1 = x0;
при этом происходит следующее: вызывается копи-конструктор твоего класса. копи-конструктор по умолчанию, просто содержимое памяти, занимаемой объектом x0 скопирует в память, занимаемую объектом x1 (в нашем случае, т.е. они оба - в стеке, для простоты примера), без никакого анализа содержимого, и для класса x1 вызывается "нормальный" конструктор. в примере с твоим классом этого вполне достаточно, но это, как тебе написали, не всегда тот случай. тогда тебе нужно копи-конструктор для класса самому создать, и там проследить, чтобы все было хорошо, по-простому говоря.
не знаю, упростил или запутал
1
Jupiter
Каратель
Эксперт С++
6561 / 3982 / 227
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
02.10.2012, 11:46 #10
novi4ok, в вашем примере конструктор копирования не вызывается
1
alsav22
5428 / 4823 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
02.10.2012, 16:05 #11
Цитата Сообщение от Jupiter Посмотреть сообщение
novi4ok, в вашем примере конструктор копирования не вызывается
Срабатывает оператор присваивания, заданный по умолчанию.
0
AnreyKazakov
Заблокирован
02.10.2012, 20:28  [ТС] #12
Больше всего путаюсь с указателями, а тут как разх с ними надо работать, вот класс создал
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using namespace std;
class vertu{
    public:
    vertu():ival(0),str(new std::string){}
    vertu(vertu &copy):ival(copy.ival),str(copy.str){}
    int ival;
    std::string* str;
    void operator()(int a,std::string* s){
        ival=a;
        str=s;      
        }   
    };
int main(){
    class vertu vert;
    int k(10);
    std::string sk("Papapap");
    vert(k,&sk);
    std::cout<<vert.ival<<" "<<*vert.str<<std::endl;
    class vertu vert2(vert);
    std::cout<<vert2.ival<<" "<<*vert2.str<<std::endl;
    return 0;
    }
Ну вот сделал передачу в объект по ссылке, сделал копирующий конструктор, но по моему что без него что с ним прекрасно работает, или я опять путаю что-нить
0
doctor_lecter
280 / 153 / 8
Регистрация: 22.09.2012
Сообщений: 283
02.10.2012, 20:31 #13
У вас str это указатель на строку, и поэтому в оригинальном объекте и его копии будет указывать на одну и ту же строку. И например при изменении строки в одном объекте будет меняться строка и в другом
2
alsav22
5428 / 4823 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
02.10.2012, 20:47 #14
Под строку выделили память, а освобождать её кто будет? Утечка памяти.

Добавлено через 48 секунд
Цитата Сообщение от AnreyKazakov Посмотреть сообщение
Ну вот сделал передачу в объект по ссылке, сделал копирующий конструктор, но по моему что без него что с ним прекрасно работает, или я опять путаю что-нить
Читайте выше. Не зря же пишут:
"Зачастую самой трудной задачей при определении конструктора копий является собственно осознание того,что он необходим"
Это как раз для вас.
1
AnreyKazakov
Заблокирован
02.10.2012, 20:54  [ТС] #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
#include <iostream>
using namespace std;
class vertu{
    public:
    vertu():ival(0),q(new int[5]){}
    //vertu(vertu &copy):ival(copy.ival),q(copy.q){}  /*1*/
    //vertu(vertu &copy):ival(copy.ival),q(new int[5]){} /*2*/
    int ival;
    int* q;
    void operator()(int a,int* qq){
        ival=a;
        q=qq;       
        }   
    };
int main(){
    class vertu vert;
    std::cout<<vert.ival<<" "<<*(vert.q)<<std::endl;
    int k(10);
    int sk[5]={1,2,3,4,5};
    vert(k,sk);
    std::cout<<vert.ival<<" "<<*(vert.q)<<std::endl;
    class vertu vert2(vert);
    std::cout<<vert2.ival<<" "<<*(vert2.q)<<std::endl;
    return 0;
    }
Под строку выделили память, а освобождать её кто будет? Утечка памяти.
Я пока допру что и где........................
0
02.10.2012, 20:54
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.10.2012, 20:54
Привет! Вот еще темы с ответами:

Конструктор копий по умолчанию. - C++
Почему, когда в vc++ vdfsadsad Добавлено через 46 секунд Почему если идёшь по коду с заходом в функцию не отображается вызов...

Классы: конструктор копий - C++
Создать конструктор копий и оператор присваивания для класса компьютер и члена класса марка Есть некоторые наброски , посмотрите...

Конструктор копий. Оператор присваивания - C++
В классе есть массив char (не динамический) размером 40 байт. Вопрос1: нужно ли для такого класса определять конструктор копий или...

Перегрузка оператора ++ , деструктор и конструктор копий - C++
Привет всем! В продолжение Этой темы появились новые вопросы и непонятки. Буду признателен за советы и разъяснения ;) Начну с...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.