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

Конструктор копирования(быстрый вопрос) - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.80
cetrael
 Аватар для cetrael
60 / 5 / 3
Регистрация: 01.10.2011
Сообщений: 93
28.11.2011, 02:09     Конструктор копирования(быстрый вопрос) #1
Вроде бы все просто и логично, но в итоге выполнения B не копируется в A :C why?
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
#include <iostream>
 
using namespace std;
 
class Int {
    int a;
public:
    Int() {a = 0;}
    Int(int A)  {a = A;}
    int getA() const { return a; }
 
    Int& operator = (const Int &obj) {
        int a;
        a = obj.a;
        return *this;
    }
 
    Int(const Int& obj) {
        int a = 0;
        a = obj.a;
    }
 
};
 
int main () {
 
 
    Int A(1);
    Int B(A);
    cout << B.getA();//Ожидал увидеть 1, а получается что-то типа -8589......
        Int C(12);
        C = A;
        cout << C.getA();//Ожидал увидеть тоже 1, а получается 12, то есть значение не изменилось.
 
 
 
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.11.2011, 02:09     Конструктор копирования(быстрый вопрос)
Посмотрите здесь:

C++ Конструктор копирования
конструктор копирования C++
Конструктор копирования C++
C++ конструктор копирования
Конструктор копирования C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
fom4ik
49 / 7 / 1
Регистрация: 07.11.2010
Сообщений: 52
28.11.2011, 02:12     Конструктор копирования(быстрый вопрос) #2
он должен возвращать новый созданный объект
BRcr
 Аватар для BRcr
4003 / 2292 / 155
Регистрация: 03.02.2011
Сообщений: 5,064
Записей в блоге: 10
28.11.2011, 02:14     Конструктор копирования(быстрый вопрос) #3
Цитата Сообщение от cetrael Посмотреть сообщение
Int(const Int& obj) {
int a = 0;
a = obj.a;
}
Намек ясен?
cetrael
 Аватар для cetrael
60 / 5 / 3
Регистрация: 01.10.2011
Сообщений: 93
28.11.2011, 02:14  [ТС]     Конструктор копирования(быстрый вопрос) #4
Цитата Сообщение от fom4ik Посмотреть сообщение
он должен возвращать новый созданный объект
Кто он, какой объект? По-подробней, пожалуйста, все-таки ночь за окном )
Сыроежка
Заблокирован
28.11.2011, 02:15     Конструктор копирования(быстрый вопрос) #5
cetrael, У вас должно все копироваться. По крайней мере визуально я не вижу причин некорректной работы конструктора копирования.

Пардон, я уже устал. Вы создаете в своемконструкторе локальную переменную с тем же самым именем, что и член класса, Эта локальная переменная скрывает имя члена класса. Поэтому значение получает не член класса, а ваша локальная переменная.
cetrael
 Аватар для cetrael
60 / 5 / 3
Регистрация: 01.10.2011
Сообщений: 93
28.11.2011, 02:17  [ТС]     Конструктор копирования(быстрый вопрос) #6
Каааак вы так быстро соображаете ночью?
Все большое спасибо, работа пошла в гору
Bers
Заблокирован
28.11.2011, 02:20     Конструктор копирования(быстрый вопрос) #7
Обратите внимание на этот код:
C++
1
2
3
4
5
6
Int(const Int& obj) {
 int a = 0; //здесь объявляется новая переменная
 a = obj.a; //этой новой переменной даётся значение
 }// по выходу из тела функции переменная уничтожается
//переменная данная-член остаётся без изменений
//вы уверены, что это именно то, что вы хотели?
cetrael
 Аватар для cetrael
60 / 5 / 3
Регистрация: 01.10.2011
Сообщений: 93
28.11.2011, 02:21  [ТС]     Конструктор копирования(быстрый вопрос) #8
Цитата Сообщение от BRcr Посмотреть сообщение

Не по теме:


А можно грамотным языком услышать, что за бред я писал.
Получается я создавал ещё одну переменную, точно такую же, как в классе? Тогда почему не было неопределенности?
Сыроежка
Заблокирован
28.11.2011, 02:23     Конструктор копирования(быстрый вопрос) #9
Цитата Сообщение от cetrael Посмотреть сообщение
А можно грамотным языком услышать, что за бред я писал.
Получается я создавал ещё одну переменную, точно такую же, как в классе? Тогда почему не было неопределенности?
переменные во вложенных блоках скрывают переменные, объявленные во внешних блоках. Например,

C++
1
2
3
4
5
6
7
8
9
10
int i = 1;
 
int main()
{
   int i = 2;
   {
      int i = 3;
      for ( int i = 4; i > ::i; --i );
   }
}
Bers
Заблокирован
28.11.2011, 02:25     Конструктор копирования(быстрый вопрос) #10
Цитата Сообщение от cetrael Посмотреть сообщение
Тогда почему не было неопределенности?
новая переменная скрывала собой объявленную в классе

Можно например, написать так:
C++
1
2
3
4
Int(const Int& obj) {
        int a = 0;
       Int::a = obj.a; //разрешение контекста
    }
С помощью разрешения контекста можно явно указывать компилятору, какую именно "версию" данных вы имеете ввиду.
В данном случае получится, что локальная переменная инициализируется, но не используется.
А настоящий данный-член получит корректное значение
Сыроежка
Заблокирован
28.11.2011, 02:34     Конструктор копирования(быстрый вопрос) #11
Цитата Сообщение от Bers Посмотреть сообщение
новая переменная скрывала собой объявленную в классе

Можно например, написать так:
C++
1
2
3
4
Int(const Int& obj) {
        int a = 0;
       Int::a = obj.a; //разрешение контекста
    }
С помощью разрешения контекста можно явно указывать компилятору, какую именно "версию" данных вы имеете ввиду.
В данном случае получится, что локальная переменная инициализируется, но не используется.
А настоящий данный-член получит корректное значение
Что это за "разрешение контекста"? Такой синтаксис Int::a вы можете использовать только для статических членов класса. В данном же случае следовало записать this->a.

Добавлено через 3 минуты
Bers, Прошу извинения, вы правы. Можно внутри класса использовать такое квалифицированное имя.
Bers
Заблокирован
28.11.2011, 02:36     Конструктор копирования(быстрый вопрос) #12
Цитата Сообщение от Сыроежка Посмотреть сообщение
Что это за "разрешение контекста"? Такой синтаксис Int::a вы можете использовать только для статических членов класса. В данном же случае следовало записать this->a.
"разрешение контекста" указывает компилятору, какая версия данных должна быть использована.
Выше был пример для данных-членов.
Вот другой пример:

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
struct Base 
{
    void View() {std::cout<< "Base\n"; } 
};
 
struct Der: public Base 
{ 
    void View() 
    {
        std::cout<< "Der\n"; 
        Base::View(); //разрешение контекста указывает
                      //компилятору какую версию метода нужно запустить
                      //если забудите указать - получите рекурсию
    } 
};
 
 
int main()
{
 
    Der test;
    test.View();
    EndProgramm();
}
Добавлено через 1 минуту
Цитата Сообщение от Сыроежка Посмотреть сообщение
Bers, Прошу извинения, вы правы. Можно внутри класса использовать такое квалифицированное имя.
Ничего-ничего. Вы своими замечаниями частенько мне мозги прочищаете. Таки, только на пользу идёт)
greeezz
272 / 165 / 4
Регистрация: 10.07.2011
Сообщений: 441
28.11.2011, 03:54     Конструктор копирования(быстрый вопрос) #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
#include <iostream>
 
using namespace std;
 
class Int {
public:
        Int(int b = 0){
            a = b;
        }
 
        int getInt() const {
            return a;
        }
 
        const Int &operator=(const Int &obj) {
            if(&obj != this){
                this->a = obj.a;
            }
                return *this;  //для выражений типа  x = y = z
        }
 
private:
        int a;
};
 
int main () {
        Int A(1);
        Int B(A);
        cout << "OBJECT B.getInt() : " <<B.getInt() << endl;
        Int C(12);
        cout << "OBJECT before assignment C.getInt() : " << C.getInt() << endl;
        C = A;
        cout << "OBJECT after assignment C.getInt() : " << C.getInt();
}
Сыроежка
Заблокирован
28.11.2011, 04:42     Конструктор копирования(быстрый вопрос) #14
Цитата Сообщение от greeezz Посмотреть сообщение
ваш класс я бы сделал как-то так:
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
#include <iostream>
 
using namespace std;
 
class Int {
public:
        Int(int b = 0){
            a = b;
        }
 
        int getInt() const {
            return a;
        }
 
        const Int &operator=(const Int &obj) {
            if(&obj != this){
                this->a = obj.a;
            }
                return *this;  //для выражений типа  x = y = z
        }
 
private:
        int a;
};
 
int main () {
        Int A(1);
        Int B(A);
        cout << "OBJECT B.getInt() : " <<B.getInt() << endl;
        Int C(12);
        cout << "OBJECT before assignment C.getInt() : " << C.getInt() << endl;
        C = A;
        cout << "OBJECT after assignment C.getInt() : " << C.getInt();
}
У вашей реализации имеется немало недостатков. Конструктор лучше писать следующим образом

C++
1
        Int( int a = 0 ) : x( a ) {}
то есть лучше задать список инициализации.

Функцию getInt лучше переименовать в getx или get_x. Дело в том, Int - это тип, и getInt звучит как получить тип, вместо того, чтобы получить значение члена объекта.

C++
1
        int getx() const { return ( x ); }
Не понятно почему оператор присваивания возвращает константную ссылку на объект. В С++ значением, возвращаемым оператором присваивания является lvalue, поэтому квалификатор const здесь не удел. То есть вместо вашего

C++
1
2
3
4
5
6
        const Int &operator=(const Int &obj) {
            if(&obj != this){
                this->a = obj.a;
            }
                return *this;  //для выражений типа  x = y = z
        }
следует написать

C++
1
2
3
4
5
        Int & operator =( const Int &obj )
        {
            x = obj.x;
              return ( *this );        }
        }
И нет необходимости делать проверку вида this != &obj.
На самом деле для этого класса ни конструктор копирования, ни копирующий оператор присваивания не требуются.
А что требуется, так как это перегрузка всех арифметических операторов, которые используются с целочисленными типами, а также операторы сравнения, битовые операторы и т.д.
greeezz
272 / 165 / 4
Регистрация: 10.07.2011
Сообщений: 441
28.11.2011, 05:47     Конструктор копирования(быстрый вопрос) #15
Сыроежка,

Не по теме:

употрбляйте пожалуйста для ясности более правильные слова. слово "недостатки" является негативным и подразумевает что в приведенном мной коде есть серьезные ошибки которые могут повлеч за собой какие либо сбои в работе программы. если таковые на ваш взгляд есть то извольте привести примеры. При каких обстоятельствах мой код может быть плохим. За что вам буду очень благодарен.


теперь по теме.
Цитата Сообщение от Сыроежка Посмотреть сообщение
У вашей реализации имеется немало недостатков. Конструктор лучше писать следующим образом

C++
1
        Int( int a = 0 ) : x( a ) {}
то есть лучше задать список инициализации.
я не инициализирую константные переменные и по этому использование такого метода инициализации не панацея в данном примере.

Цитата Сообщение от Сыроежка Посмотреть сообщение
Функцию getInt лучше переименовать в getx или get_x. Дело в том, Int - это тип, и getInt звучит как получить тип, вместо того, чтобы получить значение члена объекта.

C++
1
        int getx() const { return ( x ); }
совершенно согласен.
Цитата Сообщение от Сыроежка Посмотреть сообщение
Не понятно почему оператор присваивания возвращает константную ссылку на объект. В С++ значением, возвращаемым оператором присваивания является lvalue, поэтому квалификатор const здесь не удел. То есть вместо вашего
const нужен чтобы избежать инцидентов вот такого характера : (A = B) = C;


Цитата Сообщение от Сыроежка Посмотреть сообщение
И нет необходимости делать проверку вида this != &obj.
как раз дело в том что нет необходимости присваивать значения полей объекта к ним же самим

Цитата Сообщение от Сыроежка Посмотреть сообщение
А что требуется, так как это перегрузка всех арифметических операторов, которые используются с целочисленными типами, а также операторы сравнения, битовые операторы и т.д.
Это где автор темы такое написал?
Я привел пример реализации класса на основе того что нужно было автору. Если попросит помочь с перегрузкой других операторов. будем делать другие примеры.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
28.11.2011, 08:36     Конструктор копирования(быстрый вопрос) #16
Цитата Сообщение от greeezz Посмотреть сообщение
const нужен чтобы избежать инцидентов вот такого характера : (A = B) = C;
Но перестанут работать выражения вида
(A=B)++;
Нужно стараться сохранять семантику языка, поэтому const "лишний".

Цитата Сообщение от greeezz Посмотреть сообщение
как раз дело в том что нет необходимости присваивать значения полей объекта к ним же самим
Эта проверка нужно не столько для оптимизации, сколько для обеспечения работы присваивания в классах с динамическим выделением данных для полей. Для объектов-значений данная проверка не нужна. Для красиво спроектированных классов она тоже не нужна.

Добавлено через 2 минуты

Не по теме:

Цитата Сообщение от cetrael Посмотреть сообщение
быстрый вопрос
На две страницы.

Сыроежка
Заблокирован
28.11.2011, 14:55     Конструктор копирования(быстрый вопрос) #17
Цитата Сообщение от greeezz Посмотреть сообщение
[b]

const нужен чтобы избежать инцидентов вот такого характера : (A = B) = C;
О каком "инциденте" вы ведете речь? Это семантика языка С++. Простой пример,

C++
1
2
3
int x, y = 1, z = 2;
 
( x = y ) = z;
Я вам же написал, что оператор присваивания в С++ возвращает lvalue. Вы же пропускаете это важное замечание и говорите о каком-то "инциденте". Класс Int должен полностью имитировать работу с фундаментальными типами, поэтому данный "инцидент" для него обязан присутствовать.

как раз дело в том что нет необходимости присваивать значения полей объекта к ним же самим
Работая с целыми числами вы можете написать x = x;, поэтому незачем делать лишнию проверку в операторе присваивания, которая по объектному коду занимает больше места, чем обыное присваивание переменной типа int самой себе. Дело в том, что компилятор может оптимизировать код x = x;, то есть вообще не генерировать для этой строки никакого объектного кода, а, вот, для строки if ( this != &obj ) компилятор обязан сгенерировать код! То есть вы простое заменяете на сложное, при этом не получая никаких преимуществ, а даже теряя в эффективности.
Chelioss
179 / 179 / 4
Регистрация: 08.01.2011
Сообщений: 1,131
28.11.2011, 16:05     Конструктор копирования(быстрый вопрос) #18
Цитата Сообщение от Deviaphan Посмотреть сообщение
(A=B)++;
Постинкремент для lvalue?
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
28.11.2011, 16:09     Конструктор копирования(быстрый вопрос) #19
Цитата Сообщение от Chelioss Посмотреть сообщение
Постинкремент для lvalue?
Ага. Инкрементим А, которому сперва присвоили В.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.11.2011, 16:10     Конструктор копирования(быстрый вопрос)
Еще ссылки по теме:

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

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

Или воспользуйтесь поиском по форуму:
Bers
Заблокирован
28.11.2011, 16:10     Конструктор копирования(быстрый вопрос) #20
Цитата Сообщение от Chelioss Посмотреть сообщение
Постинкремент для lvalue?
Ага. Сначала скобки, потом ++
Yandex
Объявления
28.11.2011, 16:10     Конструктор копирования(быстрый вопрос)
Ответ Создать тему
Опции темы

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