Другие языки программирования и технологии

Как перегружать оператор присваивания?

Вот есть рабочий код: Допустим надо присвоить одну матрицу другой: matrix m1 = m2; matrix& operator= (matrix &mx){} Насколько я понимаю matrix& - тип возвращаемого значения функции. Тут настораживает, что возвращаемое значение ссылка. Это нормально? mx - правый операнд присваивания А что является левым Может здесь объяснят понятнее. На форуме любят писать "Вставь этот код, всё будет работать". А я хочу понять.
левого операнда - нет, оператор присваивания - унарный, соответсвтенно слева будет только ожидающая результата переменная. То что вас настораживают ссылки - это хорошо.. . потому что ссылки - это опасно, что в сибирь, что в памяти. Но в данном случае нужно, наверное, вспомнить, что ваша матрица - это класс, а экземпляры класса, обычно, представляются в виде ссылок поскольку являются динамическими переменными, соответсвенно в таком описании оператор присваивания будет прозрачно работать с такими объектами, без дополнительных танцев с бубном по приведению типа.
а опасность ссылок в этом случае заключается в том, что такой оператор будет неявно повторять констуктор с параметром создания - готовым объектом, что неизбежно привлечет к утечкам памяти, так как использование этого оператора направо и налево будет плодить матрицы, которые уже не нужны, но место в куче для них уже отъели.
ИД
Иван Дроздюк
8 642
Лучший ответ
Ты не совсем правильно понимаешь проблему. А она начинается со второй строчки твоего вопроса.
matrix m1 = m2;
Что здесь происходит? У тебя создаётся новая матрица m1 и она ИНИЦИАЛИЗИРУЕТСЯ значениями матрицы m2.Как раз в этом случае перегрузка оператора присваивания не нужна. Здесь могут произойти два варианта.
1)Произойдёт побитовое копирование. В m1 запишутся все данные из m2.Это не опасно, если в m2 не полей-указателей. Если они есть, то в поля m1 запишутся теже адреса. Когда разрушится объект m2,то освободится память по адресу в поле-указателе. Но указатель в m1 будет продолжать указывать на этот же адрес, а там уже "пусто".Это серьёзная ошибка. Для её обхода применяется вариант 2.
2)Создаётся конструктор копирования. В нём нужно для всех полей с указателями выделить свою память. Для записи
matrix m1 = m2;
если нет конструктора копирования, произойдёт побайтовое копирование. Если же определить в классе конструктор копирования, то вызовется именно он, а не перегруженный оператор присваивания. Это нужно понимать.
Оператор присваивания вызовется тогда, когда уже существующему объекту присваивается другой объект.
matrix m1; //сработал конструктор без параметров
matrix m1(12,20);//здесь сработал конструктор с параметрами
У нас теперь уже есть готовый объект m1.Теперь ему присвоим объект m2
m1=m2;
В этом случае вызовется оператор присваивания. Или оператор по умолчанию или, если оперделён в классе, то вызовется перегруженная версия.
Это нужно понимать.
Нурбол Сманов
Нурбол Сманов
9 759
Напиши подробнее, что такое matrix и из чего состоит. А то так тебе нельзя помочь.
Рекомендую тебе книгу Ivor Horton "Beginning Visual C++ 2010" (там есть по перегрузке всё).
Если это С++, то:
m1 = m2 - это тоже самое, что m1.operator=(m2). Левый операнд это m1 - он передается неявно.
Теперь по поводу ссылки: оператор присваивания возвращает ссылку на объект слева (m1) через указатель this, благодаря чему можно последовательно присваивать друг другу несколько объектов (m1 = m2 = m3). Никакой утечки памяти тут нет, так как это ссылка на уже существующий объект и новой памяти не выделяется.