Как оператор + = был реализован в C ++? - PullRequest
2 голосов
/ 03 мая 2020

Это вопрос, над которым я всегда размышлял и никогда не находил никаких ресурсов с ответом на этот вопрос. На самом деле это не только для +=, но и для его братьев и сестер, то есть -=, *=, /= и др. c. (конечно, не ==).

Рассмотрим пример,

int a = 5;
a += 4;
//this will make 'a' 9

Теперь рассмотрим эквивалентное выражение:

a = a + 4;
//This also makes 'a' 9

Если += были просто Сокращение для a = a + <rhs of +=> перегрузка + оператор также должен неявно перегружать +=, если явно не перегружено иначе. Но это не то, что происходит. Это означает, что a += b не преобразуется в a = a + b. Но тогда почему это не было реализовано таким образом? Например, не проще ли было бы просто преобразовать его в a = a + b во время компиляции, вместо того, чтобы реализовывать его отдельно как оператор сам по себе? Это также помогло бы при перегрузке операторов, где a += b, где a и b - объекты одного и того же класса, не нужно было бы явно перегружать, и простой перегрузки + было бы достаточно?

Ответы [ 2 ]

2 голосов
/ 03 мая 2020

Операторы не генерируются из других (кроме с / из <=> в C ++ 20):

, обеспечивающий operator <, не допускает a > b (что действительно "логически" эквивалентно b < a). Вы должны реализовать все (даже повторно используя некоторые).

Для классов a += b - это не сокращение для a = a + b

, а для a.operator +=(b) или operator +=(a, b)

Таким же образом a = a + b является сокращение для a.operator=(operator +(a, b)) (или его вариант)

На практике более эффективно реализовать operator+ из operator +=, чем наоборот.

Даже если пользователь может ожидать аналогичного поведения в соответствии с их именами они являются обычными функциями.

Я уже видел матричный итератор, для которого ++it увеличивает индекс столбца, тогда как it++ увеличивает индекс строки.

Если += были просто сокращением для a = a + <rhs of +=> оператор перегрузки + должен также неявно overload +=, если явно не перегружен иначе. Но это не то, что происходит. Это означает, что a += b не преобразуется в a = a + b.

(возможно), рациональным, чтобы не генерировать, может быть производительность и контроль:

Vector (для математики) или Хороший пример - матрица:

4 возможных перегрузки

Matrix operator+(Matrix&& lhs, Matrix&& rhs)      { return std::move(lhs += rhs); }
Matrix operator+(Matrix&& lhs, const Matrix& rhs) { return std::move(lhs += rhs); }
Matrix operator+(const Matrix& lhs, Matrix&& rhs) { return std::move(rhs += lhs); } // + is symmetrical :)
Matrix operator+(const Matrix& lhs, const Matrix& rhs) { auto tmp{lhs}; return tmp += rhs; }

Побочный эффект решения позволяет придавать операторам различные значения, как «оператор имени»:

if (42 <in> std::vector{4, 8, 15, 16, 23, 42})
2 голосов
/ 03 мая 2020

Использование a = a + b подразумевает использование назначения копирования (поскольку используется operator =). С другой стороны, a += b по умолчанию является составным присваиванием.

Согласно cppreference ,

оператор присваивания копии заменяет содержимое объекта a с копией содержимого b (b не изменено).

и

составные операторы присваивания заменяют содержимое объекта a на результат двоичного поэтому операция между предыдущим значением a и значением b.

Использование a = a + b приведет к ненужному использованию памяти, поскольку a необходимо скопировать один раз, прежде чем его значение будет изменено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...