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

Переопределение оператора присваивания - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 30, средняя оценка - 4.93
_lacrimosa_
1 / 1 / 0
Регистрация: 10.06.2010
Сообщений: 26
12.06.2010, 00:01     Переопределение оператора присваивания #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
class TClass
{
    private:
        float* A;
        int N;
    public:
        TClass(int _N)                      //конструктор
        {
            N = _N;
            A = new float [N];
        }
        ~TClass()                           //деструктор
        {
            delete [] A;
        }
        TClass& operator= (const TClass& B) //переопределённый оператор =
        {
            if (this == &B)
                return *this;
 
            N = B.N;
            delete [] A;
            A = new float [N];
            memcpy(A,B.A,N*sizeof(float));
            
            return *this;
        }
};
Суть проблемы в поведении операции присваивания. Примеры использования объектов класса:

1) В случае, если объекты класса статические, то всё ОК:

C++
1
2
3
4
5
6
void main()
{
    TClass C(10);
    TClass D(5);
    C=D;
}
2) В случае, если объекты класса создаются динамически:

C++
1
2
3
4
5
    TClass* C = new TClass(10);
    TClass* D = new TClass(5);
    C=D;  // FAIL
    delete C;
    delete D;
После выполнения операции присваивания во 2-ом случае, объекты C и D идентичны. Более того, расположены на одном участке памяти, причём массивы, содержащиеся в C и D, также расположены на одном участке памяти. При вызове delete C память освобождается. При вызове delete D получается ситуация, когда нужно удалить ту же самую память (удалённую при помощи delete C, так как C=D). Отмечу, что оператор = вообще не вызывается при выполнении программы, что странно. Если не ошибаюсь, то вызывается оператор присваивания по умолчанию и объекты становятся копиями. Всё работает как надо, если:

вместо

C++
1
C=D;  // FAIL
использовать

C++
1
C->operator=(*D);
Собственно вопрос, как такого избежать и что предпринять? Требуемый результат: данные в C и D должны быть одинаковые, но адреса объектов различны.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
12.06.2010, 00:01     Переопределение оператора присваивания
Посмотрите здесь:

Перегрузка оператора присваивания C++
Переопределение операции присваивания C++
C++ Перегрузка оператора присваивания
Насчет оператора присваивания C++
C++ Проверка оператора присваивания
Перегрузка оператора присваивания C++
Для чего нужно переопределение оператора присваивания? C++
C++ Переопределение операции присваивания

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

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9373 / 5423 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
12.06.2010, 00:36     Переопределение оператора присваивания #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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>
#include <algorithm>
 
class TClass {
private:
    float* A;
    int N;
public:
    TClass() : N(0), A(0) { }
    TClass(int _N) {
        N = _N;
        A = new float [N];
    }
    TClass(const TClass & t) {
        *this = t;
    }
    ~TClass() {
        if ( A )
            delete [] A;
    }
    const TClass& operator= (const TClass& B) {
        if (this == &B)
            return *this;
 
        N = B.N;
        if ( A )
            delete [] A;
        A = new float [N];
        std::copy(B.A, B.A + B.N, A);
//      memcpy(A,B.A,N*sizeof(float));
                       
        return *this;
    }
    
    friend std::ostream & operator << (std::ostream & ost, const TClass & t) {
        for ( int i = 0; i < t.N; ++i )
            ost << t.A[i] << std::endl;
        return ost;
    }
    
    friend std::istream & operator >> (std::istream & ist, TClass & t) {
        for ( int i = 0; i < t.N; ++i )
            ist >> t.A[i];
        return ist;
    }
};
 
int main(){
    TClass * a, * b, * c;
    const int size = 3;
    
    std::cout << "enter " << size << " double values: " << std::endl;
    a = new TClass(size);
    std::cin >> *a;
    std::cout << "\nA values:\n" << *a << std::endl;
    
    b = new TClass(*a);
    delete a;
    std::cout << "B values:\n" << *b << std::endl;
    
    c = new TClass();
    *c = *b;
    delete b;
    std::cout << "C values:\n" << *c << std::endl;
    
    delete c;
    return 0;
}
Добавлено через 4 минуты
Цитата Сообщение от _lacrimosa_ Посмотреть сообщение
C=D;
ну ещё бы! копировать нужно не указатели, а их значения!
C++
1
*C = *D;
_lacrimosa_
1 / 1 / 0
Регистрация: 10.06.2010
Сообщений: 26
12.06.2010, 00:42  [ТС]     Переопределение оператора присваивания #3
Спасибо. Особенно за строчку 62 =) Навело на правильную мысль.

Мне видимо нужно было вместо C=D использовать *C=*D. То есть в первом случае я копировал адрес объекта, а не сам объект. Теперь дошло.
Yandex
Объявления
12.06.2010, 00:42     Переопределение оператора присваивания
Ответ Создать тему
Опции темы

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