Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.52/48: Рейтинг темы: голосов - 48, средняя оценка - 4.52
Заблокирован
1

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

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

Author24 — интернет-сервис помощи студентам
Объясните, пожалуйста, на максимально простом языке, чем отличается конструктор от конструктора копий?
Может это и одно и то же, хотя вряд ли, в книжке в разных разделах инфа выложена...
под конструктором я понимаю что-то вроде:
C++
1
2
3
4
class as{
as():a(155){}
int a;
};
Если класс объявлен, а переменная а не инициализирована, то значение а 155.
А что такое конструктор копий? Злость берет, что нифига не понимаю.... Единственное порадовало: "Зачастую самой трудной задачей при определении конструктора копий является собственно осознание того,что он необходим"
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.10.2012, 00:13
Ответы с готовыми решениями:

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

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

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

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

22
2277 / 1768 / 741
Регистрация: 27.07.2012
Сообщений: 5,251
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
Заблокирован
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
5 / 5 / 5
Регистрация: 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
5498 / 4893 / 831
Регистрация: 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
2277 / 1768 / 741
Регистрация: 27.07.2012
Сообщений: 5,251
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
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
02.10.2012, 11:08 7
Есть копирующий оператор присваивания, он превращает один уже существующий объект в точную копию другого, а есть копирующий конструктор, он создаёт копию в новом объекте.
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
02.10.2012, 11:14 8
alsav22,
John Prick,
C++
1
String ss1 = "test test";
Инициализация копированием. При проверке эквивалентно
C++
1
String ss1 = String("test test");
Компилятор ОБЯЗАН проверить, что есть подходящий копирующий конструктор, а будет-ли вызван или нет зависит от компилятора и опций.
1
556 / 510 / 25
Регистрация: 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
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
02.10.2012, 11:46 10
novi4ok, в вашем примере конструктор копирования не вызывается
1
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
02.10.2012, 16:05 11
Цитата Сообщение от Jupiter Посмотреть сообщение
novi4ok, в вашем примере конструктор копирования не вызывается
Срабатывает оператор присваивания, заданный по умолчанию.
0
Заблокирован
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
284 / 157 / 30
Регистрация: 22.09.2012
Сообщений: 283
02.10.2012, 20:31 13
У вас str это указатель на строку, и поэтому в оригинальном объекте и его копии будет указывать на одну и ту же строку. И например при изменении строки в одном объекте будет меняться строка и в другом
2
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
02.10.2012, 20:47 14
Под строку выделили память, а освобождать её кто будет? Утечка памяти.

Добавлено через 48 секунд
Цитата Сообщение от AnreyKazakov Посмотреть сообщение
Ну вот сделал передачу в объект по ссылке, сделал копирующий конструктор, но по моему что без него что с ним прекрасно работает, или я опять путаю что-нить
Читайте выше. Не зря же пишут:
"Зачастую самой трудной задачей при определении конструктора копий является собственно осознание того,что он необходим"
Это как раз для вас.
1
Заблокирован
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
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
02.10.2012, 20:55 16
Если в вашем коде, из 12 поста, определить деструктор:
C++
1
2
3
4
~vertu()
{
     delete str;
}
, то результат работы будет уже такой:
Миниатюры
Что такое конструктор копий?  
1
Заблокирован
02.10.2012, 20:58  [ТС] 17
Чуть начинаю догонять .... это хорошо особенно выражение понравилось "повреждение кучи"
0
5498 / 4893 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
02.10.2012, 21:19 18
Кстати, в вашем коде из 12 поста, вообще не работает конструктор копирования. Там не понятно, что работает, из-за того, что объект содержит указатель, на строковую лексему в статической памяти. Чтобы нормально всё работало, нужно так переписать:
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 <string>
#include <iostream>
using namespace std;
 
class vertu
{
    public:
     vertu() : ival(0), str(new string)
     {}
     
     vertu(const vertu &copy) 
     {
        ival = copy.ival;
        str = new string;
        *str = *copy.str;
    }
     
     int ival;
     string* str;
     
     void operator()(int a, string* s)
     {
        ival = a;
        str = new string;
        *str = *s;
     } 
    
    ~vertu()
    {
        delete str;
    }  
};
 
int main()
{
    vertu vert;
    int k(10);
    string sk("Papapap");
    
    vert(k, &sk);
    cout << vert.ival << " " << *vert.str << endl;
    
    vertu vert2(vert);
    cout << vert2.ival << " " << *vert2.str << endl;
 
    cin.get();
    return 0;
 }
1
Заблокирован
02.10.2012, 21:27  [ТС] 19
Цитата Сообщение от alsav22 Посмотреть сообщение
ival = copy.ival;
str = new std::string;
*str = *(copy.str);
Во, спасибо, а я все гадал как это можно сделать, оказывается просто через ; ....
0
5 / 5 / 5
Регистрация: 25.09.2012
Сообщений: 42
02.10.2012, 22:40 20
Цитата Сообщение от alsav22 Посмотреть сообщение
В вашем коде он и не дожен был вызываться
спасибо, понял не сразу как все работает

Цитата Сообщение от John Prick Посмотреть сообщение
если в классе объявлен копирующий конструктор, то копирующего конструктора по умолчанию в нём уже нет
а вот это стало новостью для меня, спасибо

остался небольшой вопрос по листингу, который привел в 4-м посте
почему же появляются ошибки, если отсутствует идентификатор "const"

C++
1
2
3
4
5
6
              String(const String &T)            //если не проставить "const" компилятор выдает ошибку
                     {                                 // при этом в исходном примере const  не стоит 
                     cout << "\nkopirovanie\n";
                     ptr = T.ptr;
                     (ptr -> count)++;
                     }
0
02.10.2012, 22:40
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.10.2012, 22:40
Помогаю со студенческими работами здесь

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

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

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

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

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

С++ Конструктор копий. Функция, работающая с объектами
Конструктор копий должен работать в след. ситуациях: 1) В объявлении объекта, когда один объект...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru