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

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

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 118, средняя оценка - 4.68
Викдон
67 / 67 / 4
Регистрация: 21.11.2008
Сообщений: 226
#1

Конструктор копирования - C++

26.02.2009, 22:51. Просмотров 14647. Ответов 19
Метки нет (Все метки)

вот есть класс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Mnojestvo{   //Класс Множество
 public:
     Mnojestvo(Mnojestvo & rN); //Конструктор копирования
     Mnojestvo(int n){FMas=new char [n];} //Конструктор для итогого множества С
     Mnojestvo(int n,char*ptr); 
     ~Mnojestvo(){delete [] FMas;};
     Mnojestvo Union(Mnojestvo &P) const; //Метод "Объединение"
     Mnojestvo Cross(Mnojestvo &P) const;// Метод "Пересечение"
     void Insert_Elem(char elem) ; //Метод "Добавление элемента
     void View_Set(); //Получение значения множества
     Mnojestvo operator + (Mnojestvo &P); //Пререгрузка операции "+"
     Mnojestvo operator - (Mnojestvo &P); //Перегрузка операции "-"
     int Proverka(char elem); //Проверка элемента на вхождение в множество
     void operator =(Mnojestvo &T);
   // методы
 private:
    char*FMas; //Указатель на массив символов
    int count; //Число элементов в множестве
};
вот конструктор копирования:
C++
1
2
3
4
5
6
7
//Конструктор копирования
Mnojestvo::Mnojestvo(Mnojestvo &rN){
    FMas= new char [rN.count];
    count=rN.count;
    for(int i=0;i<rN.count;i++)
        FMas[i]=rN.FMas[i];
}
Суть задачи объявить два объекта представляющих из себя два множества.

вот я делал операцию объединения этих множеств так:

С=А+B;

C++
1
2
3
4
5
// Перегрузка операции "+"
 Mnojestvo Mnojestvo::operator +(Mnojestvo &rB){
    
return Union(rB);                      //Почему не создается копия копии объекта Time?
 }
сам метод Union:
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
 //Метод Union
 Mnojestvo Mnojestvo::Union(Mnojestvo &P) const{ 
     
     char UnionMas [20]; //Массив "объединения"
     char elem;
     int counter=count;
     bool flag;
      
       for(int i=0;i<count;i++){   //Заполняем массив объединения множеством текущего объекта
          UnionMas[i]=FMas[i];
       }
 
      // Заносив в массив "Объединения" только те элементы мн-ва входного объекта которых нет в массиве "объединение"
       for(int j=0;j<P.count;j++){  //Проходим по множеству входного объекта
         elem=P.FMas[j];
         flag=false;
          for(int k=0;k<count;k++){  //Бегаем по this множеству
              if (elem==FMas[k])
                  flag=true;
          }
        if (flag==false){
            UnionMas[counter]=elem;
            counter++;
        }
       
      }//for
  
       Mnojestvo Time(counter,UnionMas); //Создаем Временный объект
       
       
 
    return Time ; 
 }
В методе Union создается временный объект Time и в строке метода Union "return Time" создается копия объекта Time (назовем скажем kTime), а сам Time удаляется.
В перегрузку операции "+" возвращается kTime.
Вот вопрос! когда kTime попадает в operator +() она же вызодит из области видимости? и по идее в строке метода operator + "return Union(rB)" должен вызваться конструктор копирования т.е. создать копию kTime, скажем kkTime, а сам kTime удалить? Но этого не происходит! Просто передается kTime дальше..
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.02.2009, 22:51     Конструктор копирования
Посмотрите здесь:

Создать класс "Вектор" и реализовать конструктор по умолчанию, конструктор копирования и деструктор C++
C++ Конструктор копирования
C++ конструктор копирования
C++ Не могу сделать чтобы класс содержал основной конструктор и конструктор копирования
C++ Не могу правильно сделать конструктор и конструктор копирования и принадлежность точки с заданными координатами треугольнику
Конструктор инициализации, конструктор копирования, деструктор C++
C++ Конструктор копирования
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ISergey
Maniac
Эксперт С++
1346 / 879 / 51
Регистрация: 02.01.2009
Сообщений: 2,643
Записей в блоге: 1
26.02.2009, 23:14     Конструктор копирования #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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
using namespace std;
 
class Employ
{
public:
    Employ(){ cout << "standard constructor" <<endl; };
    Employ(const Employ &other)
    {
        cout << "copy constructor" <<endl;
        *this = other;
    }
    ~Employ() { cout << "standard destructor" <<endl; }
 
    Employ& operator = (const Employ &other)
    {
        cout << "Employ& operator = (const Employ &other)" <<endl;
        data = other.data;
        return *this;
    }
 
    Employ operator + (const Employ &other) const
    {
        cout<< "Employ operator + (const Employ &other)" <<endl;
        return foo(other);
    }
 
    Employ foo(const Employ &other) const
    {
        cout<< "Employ foo(const Employ &other)" <<endl;
        Employ temp;
        temp.data += other.data;
        return temp;
    }
private:
    int data;
 
};
int main()
{ 
    Employ em;
    Employ emp;
    Employ x;
    x = em + emp;
    return 0;
}
Викдон
67 / 67 / 4
Регистрация: 21.11.2008
Сообщений: 226
27.02.2009, 00:52  [ТС]     Конструктор копирования #3
а что в этой стоке делается:
C++
1
temp.data += other.data
C++
1
temp.data=temp.data+other.data; ??
и если так то почему не вызывается operator + ?
ISergey
Maniac
Эксперт С++
1346 / 879 / 51
Регистрация: 02.01.2009
Сообщений: 2,643
Записей в блоге: 1
27.02.2009, 00:59     Конструктор копирования #4
data это переменая типа int, просто для примера сумируем.
Employ::operator+ там и не должен вызываться!.
Викдон
67 / 67 / 4
Регистрация: 21.11.2008
Сообщений: 226
27.02.2009, 01:49  [ТС]     Конструктор копирования #5
а ну да))

ну вот что я и имел ввиду в строке operetor + "return foo(other);" локальная копия созданная функцией foo (копия Temp) выходит из области видимости в строке
"return foo(other);" но конструктор копирования не вызывается, а сразу эта копия передается дальше...почему?
ISergey
Maniac
Эксперт С++
1346 / 879 / 51
Регистрация: 02.01.2009
Сообщений: 2,643
Записей в блоге: 1
27.02.2009, 02:19     Конструктор копирования #6
ну тут компилятор шото мутит. интеловский вобще не вызывает конструктор копирования.
Викдон
67 / 67 / 4
Регистрация: 21.11.2008
Сообщений: 226
27.02.2009, 02:21  [ТС]     Конструктор копирования #7
т.е. он должен вызывать но это уже сам компилятор его не вызывает? пишу на Visual Studio 2005.
ISergey
Maniac
Эксперт С++
1346 / 879 / 51
Регистрация: 02.01.2009
Сообщений: 2,643
Записей в блоге: 1
27.02.2009, 02:32     Конструктор копирования #8
оптимизатор наверно какойто срабатывает.
вот скиншоты Конструктор копирования Конструктор копирования
ISergey
Maniac
Эксперт С++
1346 / 879 / 51
Регистрация: 02.01.2009
Сообщений: 2,643
Записей в блоге: 1
27.02.2009, 02:49     Конструктор копирования #9
gcc вобще такой результат выдал
Конструктор копирования
Викдон
67 / 67 / 4
Регистрация: 21.11.2008
Сообщений: 226
27.02.2009, 09:53  [ТС]     Конструктор копирования #10
В общем у каждого компилятора все по разному....
CheshireCat
Эксперт С++
2890 / 1239 / 78
Регистрация: 27.05.2008
Сообщений: 3,327
27.02.2009, 09:56     Конструктор копирования #11
Цитата Сообщение от Викдон Посмотреть сообщение
.... и по идее в строке метода operator + "return Union(rB)" должен вызваться конструктор копирования т.е. создать копию kTime, скажем kkTime, а сам kTime удалить? Но этого не происходит! Просто передается kTime дальше..
Согласно Стандарту 12.8/15, при выполнении определенных условий компилятору явно разрешено оптимизировать код и не создавать лишних копий.
Так что это нормальное и допустимое поведение.
valevgen
0 / 0 / 0
Регистрация: 28.02.2009
Сообщений: 3
28.02.2009, 20:16     Конструктор копирования #12
Mnojestvo(const Mnojestvo & rN); // (const пропущен) Сигнатура конструктора копий должна выглядеть так. Поэтому компилятор и не вызывает твой Mnojestvo(Mnojestvo & rN).
Для него это просто функция.
т.е. конструктор копий не переопределен.
мне так кажется.
Викдон
67 / 67 / 4
Регистрация: 21.11.2008
Сообщений: 226
28.02.2009, 20:49  [ТС]     Конструктор копирования #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
class 
My_class{
public:
    My_class(int a){ Age=new int(a);}
  //  My_class(My_class&re){*this=re;}
    ~My_class() {}
    void SetAge(int a){*Age=a;}
 
    int *Age;
 
};
 
My_class Foo(My_class & rD, My_class &rB);
 
int _tmain(int argc, _TCHAR* argv[])
{
 
    My_class Frisky(1); 
    My_class Boots(3);
 
    Boots=Foo(Boots,Frisky);
    return 0;
}
 
 
My_class Foo(My_class & rD, My_class &rB){
 int A,B;
  A=*rD.Age;
  B=*rB.Age;
 
 My_class Time(A+B);
 
 return Time;
}
в этой строке "Boots=Foo(Boots,Frisky)" после возвращения значения функцией Foo сначала вызывается деструктор для этого значения , а потом само значение присваивается Boots? Если так то деструктор должен удалять полностью объект и мы получается обращаемся к памяти на которую уже не указывает объект, но там все еще хранятся его данные?
CheshireCat
Эксперт С++
2890 / 1239 / 78
Регистрация: 27.05.2008
Сообщений: 3,327
28.02.2009, 21:39     Конструктор копирования #14
Цитата Сообщение от valevgen Посмотреть сообщение
Поэтому компилятор и не вызывает твой Mnojestvo(Mnojestvo & rN). Для него это просто функция. т.е. конструктор копий не переопределен. мне так кажется.
Это неверно. согласно Стандарту 12.8/2, Mnojestvo(Mnojestvo & rN) - вполне себе допустимая сигнатура конструктора копирования.

Добавлено через 7 минут 51 секунду
Цитата Сообщение от Викдон Посмотреть сообщение
в этой строке "Boots=Foo(Boots,Frisky)" после возвращения значения функцией Foo сначала вызывается деструктор для этого значения , а потом само значение присваивается Boots? Если так то деструктор должен удалять полностью объект и мы получается обращаемся к памяти на которую уже не указывает объект, но там все еще хранятся его данные?
Нет. В этой строке для значения, возвращенного функцией Foo(), создается временный анонимный (безымянный) объект, который затем присваивается Boots. Этот временный объект перестает существовать сразу после достижения потоком управления заканчивающей строку ; , которая является точкой следования, - т.е. деструктор этого объекта может быть вызван в любой момент после достижения ; по усмотрению компилятора. Но в момент выполнения Boots = .... этот объект еще существует.
Викдон
67 / 67 / 4
Регистрация: 21.11.2008
Сообщений: 226
28.02.2009, 21:43  [ТС]     Конструктор копирования #15
Так вот проблемка....у меня вот в моем классе есть указатель на int и я вот также

возвращаю временный объект из функции в строку скажем С=...; (С-объект)
а в деструкторе класса удалаю этот указатель, и в результате у меня объекту С не присваивается нужное значение, получается вызывается деструктор?
CheshireCat
Эксперт С++
2890 / 1239 / 78
Регистрация: 27.05.2008
Сообщений: 3,327
28.02.2009, 21:54     Конструктор копирования #16
Нет. Скорее всего, проблема где-то в другом месте.
Викдон
67 / 67 / 4
Регистрация: 21.11.2008
Сообщений: 226
28.02.2009, 22:02  [ТС]     Конструктор копирования #17
ну вот пример кода где такая же ситуация (может где-то я ошибаюсь, я с++ изучаю вторую неделю, изучал только паскаль и Delphi)

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
#include "stdafx.h"
#include "iostream"
using namespace std;
 
 
class My_class{
public:
    My_class(int a){ Age=new int(a);}
    My_class(My_class&re){Age=new int(*re.Age);}
    ~My_class() {delete Age;}
    void SetAge(int a){*Age=a;}
 
    int *Age;
 
};
 
My_class Foo(My_class & rD, My_class &rB);
 
int _tmain(int argc, _TCHAR* argv[])
{
 
    My_class Frisky(1); 
    My_class Boots(3);
 
    Boots=Foo(Boots,Frisky);
    return 0;
}
 
 
My_class Foo(My_class & rD, My_class &rB){
 int A,B;
  A=*rD.Age;
  B=*rB.Age;
 
 My_class Time(A+B);
 
 return Time;
}
Вот в этой строке нужное значение не присваивается:
C++
1
Boots=Foo(Boots,Frisky);
CheshireCat
Эксперт С++
2890 / 1239 / 78
Регистрация: 27.05.2008
Сообщений: 3,327
28.02.2009, 22:21     Конструктор копирования #18
Дык, естественно. У тебя ж в классе не определен operator=(). Поэтому компилятор использует его версию по умолчанию, которая в твоем случае делает совсем не то, что тебе хотелось бы.

Есть такое Правило Большой Четверки: в классе должны быть определены
- конструктор
- конструктор копирования
- оператор =
- деструктор
(они называются special member function, и им специально посвящен раздел Стандарта).
Викдон
67 / 67 / 4
Регистрация: 21.11.2008
Сообщений: 226
28.02.2009, 22:41  [ТС]     Конструктор копирования #19
его версию по умолчанию?? что он из себя представляет? и что если у меня не определена перегрузка "=" и в классе нет указателей тогда как он работает?

Добавлено через 9 минут 0 секунд
ааа т.е при использовании стандартного все же присваивается значение
C++
1
Boots=Foo(Boots,Frisky);
но затем деструктор его удаляет( память в которой хранилась это значение)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.02.2009, 22:56     Конструктор копирования
Еще ссылки по теме:

C++ Конструктор копирования
Конструктор копирования C++
Конструктор копирования C++
Конструктор копирования C++
Конструктор копирования C++

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

Или воспользуйтесь поиском по форуму:
CheshireCat
Эксперт С++
2890 / 1239 / 78
Регистрация: 27.05.2008
Сообщений: 3,327
28.02.2009, 22:56     Конструктор копирования #20
Неверно. Значение не присваивается. Версия по умолчанию просто-напросто выполняет почленное копирование данных класса; а поскольку член данных у тебя один - указатель, то просто копируется указатель. И, совершенно верно, этот указатель мгновенно начинает указывать "пальцем в небо", поскольку указываемая память тут же освобождается деструктором временного объекта......
Yandex
Объявления
28.02.2009, 22:56     Конструктор копирования
Ответ Создать тему
Опции темы

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