Почему оператор = возвращает * это?

Скажи, что я хочу переопределить operator = так что я могу сделать что-то вроде

Poly p1;  // an object representing a polynomial
Poly p2;  // another object of the same type
p2 = p1;  // assigns all the contents of p1 to p2

Тогда в моей реализации operator =У меня есть что-то вроде этого:

Poly& Poly::operator=(const Poly &source) {
// Skipping implementation, it already works fine…
return *this;
}

Не против реализации, она уже отлично работает.

Меня беспокоит то, что происходит, когда вы return *this? Я знаю, что он возвращает ссылку на объект, но происходит ли это?

p2 = &p1

8

Решение

Вы return *this так что вы можете написать нормальное соединение C ++ = заявления как:

Poly p1; //an object representing a polynomial
Poly p2;
Poly p2;

// ...

p3 = p2 = p1;  //assigns all the contents of p1 to p2 and then to p3

потому что это утверждение в основном:

p3.operator=(p2.operator=(p1));

Если p2.operator=(...) не return *this вам нечего было бы передать p3.operator=(...),

14

Другие решения

p2 = p1 это сокращение для p2.operator=(p1), Это просто зовет тебя operator= функция, которая возвращает ссылку на p2, который вы потом игнорируете. Чтобы сделать это понятным, давайте назовем это assign вместо operator=:

Poly& Poly::assign(const Poly &source) {
.
.
.
return *this;
}

Сейчас вместо p2 = p1Вы бы написали

p2.assign(p1);

В этом случае результат вызова assign игнорируется, но вы не должны игнорировать это. Например, вы можете написать:

p3.assign(p2.assign(p1));

С помощью operator= вместо assign, это становится

p3 = (p2 = p1);

но так как присваивание является ассоциативным справа, это также может быть записано как

p3 = p2 = p1;

Эта форма возможности выполнять несколько назначений одновременно изначально пришла из C и была сохранена в C ++ благодаря соглашению о возврате *this в operator=(),

5

Может возникнуть соблазн вернуть оператор копирования-назначения void если вам все равно не понадобятся цепные задания (как показано в других ответах). В конце концов, цепочечные задания часто трудно читать и понимать, поэтому недопущение их может рассматриваться как улучшение.

Тем не менее, часто упускается из виду, что void operator=(Poly& const) означает, что ваш тип больше не будет выполнять CopyAssignable концепция, который требует T& тип возврата.

Тип, который не соответствует CopyAssignable концепция не может быть официально использована для некоторых операций стандартного контейнера, например std::vector::insertЭто означает, что следующий, казалось бы, невинный фрагмент кода приводит к неопределенному поведению, даже если он, вероятно, работает отлично:

#include <vector>

struct Poly
{
void operator=(Poly const&) {} // Poly is not CopyAssignable
};

int main()
{
std::vector<Poly> v;
Poly p;
v.insert(v.begin(), p); // undefined behaviour
}

Как поясняется в стандарте C ++ в § 17.6.4.8/2.3, где говорится об ограничениях для программ, использующих стандартную библиотеку:

(…) эффекты не определено в следующих случаях:

(…) для типов, используемых в качестве аргументов шаблона при создании экземпляра
компонент шаблона, если операции над типом не реализуют
семантика применимых требований
подпункт (…).

Конечно, это точно так как из неопределенного поведения, что компилятор может игнорировать ошибку и заставить программу вести себя хорошо, в соответствии с явно предполагаемым поведением. Но это не обязательно.

Вы также должны учитывать, что вы не можете предсказать все будущие использования вашего Poly тип. Кто-то может написать некоторую шаблонную функцию, такую ​​как:

template <class T>
void f(T const& t)
{
T t2;
T t3 = t2 = t;
// ...
}

Эта функция не будет работать с вашим Poly учебный класс.

Только не нарушайте это соглашение C ++, и у вас не будет проблем.

4

что произойдет, когда вы вернетесь * это?

В вашем примере (p2 = p1;), ничего такого. Метод копий p1 в p2 и возвращает ссылку на объект this, который вызывающий код не использует.

В коде, таком как p3 = p2 = p1;первый вызов p2 = p1какие копии p1 в p2 и возвращает ссылку на p2, Затем вызывающий код копируется из этой ссылки наp2 в p3 (и игнорирует ссылку на p3 что возвращается).

(Попутно: ваши модульные тесты гарантируют, что p1 = p1 работает правильно? Это дело легко забыть!)

2

Возврат ссылки на целевой объект позволяет связывать назначения (каскадирование), а перегрузка операторов в классе следует ассоциативно справа (щелкните Вот подробные правила перегрузки операторов)

Poly a, b, c;
a = b = c;
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector