Подтвердить что ты не робот

Возвращаемое значение перегрузки оператора в С++

У меня вопрос о возвращаемом значении перегрузки оператора в С++. Как правило, я обнаружил два случая, один из которых является возвратом по значению, а один - возвратом по ссылке. Итак, что это за правило? Особенно в том случае, когда вы можете постоянно использовать оператор, например cout<<x<<y.

Например, при реализации операции + "строка + (строка)". как бы вы вернули возвращаемое значение, ref или val.

4b9b3361

Ответ 1

Некоторые операторы возвращаются по значению, некоторые по ссылке. В общем случае оператор, результат которого представляет собой новое значение (например, +, - и т.д.), Должен возвращать новое значение по значению и оператор, результат которого является существующим значением, но изменен (например, <, + =, - = и т.д.), должен вернуть ссылку на измененное значение.

Например, cout является std::ostream, а вставка данных в поток - операция модификации, поэтому для реализации оператора << для вставки в ostream оператор определяется следующим образом:

std::ostream& operator<< (std::ostream& lhs, const MyType& rhs)
{
  // Do whatever to put the contents of the rhs object into the lhs stream
  return lhs;
}

Таким образом, когда у вас есть составной оператор типа cout << x << y, сначала оценивается подвыражение cout << x, а затем вычисляется выражение [result of cout << x ] << y. Так как оператор << на x возвращает ссылку на cout, выражение [result of cout << x ] << y эквивалентно cout << y, как и ожидалось.

И наоборот, для "string + string" результат представляет собой новую строку (обе исходные строки не изменяются), поэтому она должна возвращаться по значению (в противном случае вы возвращали бы ссылку на временную, которая представляет собой undefined поведение).

Ответ 2

Чтобы попытаться ответить на вопрос о строках, оператор +() для строк почти всегда реализуется как свободная (нечлена) функция, так что неявные преобразования могут выполняться по любому из параметров. Вот так вы можете сказать такие вещи, как:

string s1 = "bar";
string s2 = "foo" + s1;

Учитывая это, и мы видим, что ни один из параметров не может быть изменен, он должен быть объявлен как:

RETURN_TYPE operator +( const string & a, const string & b );

На данный момент мы игнорируем RETURN_TYPE. Поскольку мы не можем вернуть ни один из параметров (потому что мы не можем их изменить), реализация должна создать новое, объединенное значение:

RETURN_TYPE operator +( const string & a, const string & b ) {
    string newval = a;
    newval += b;    // a common implementation
    return newval;
}

Теперь, если мы сделаем ссылку RETURN_TYPE ссылкой, мы вернем ссылку на локальный объект, который является хорошо известным no-no, поскольку локальный объект не существует вне функции. Поэтому наш единственный выбор - вернуть значение, т.е. Копию:

string operator +( const string & a, const string & b ) {
    string newval = a;
    newval += b;    // a common implementation
    return newval;
}

Ответ 3

Если вы хотите, чтобы ваш оператор перегружался, чтобы вести себя как встроенный оператор, это правило довольно просто; стандарт точно определяет, как ведут себя встроенные операторы, и укажет, является ли результат встроенного файла rvalue или lvalue.

Правило, которое вы должны использовать:

  • если встроенный оператор возвращает rvalue, тогда ваша перегрузка должна вернуть ссылку
  • если встроенный возвращает lvalue, тогда ваша перегрузка должна вернуть значение

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

Например, KennyTM отметил в комментарии к другому ответу, что перегрузка потока для операторов << и >> возвращает ссылку на левый операнд, а не то, как работают встроенные функции. Но дизайнеры интерфейса потока сделали это, так что входы/выходы могут быть привязаны.

Ответ 4

В зависимости от оператора вам может потребоваться вернуть значение.

Если оба варианта могут использоваться, как в случае оператора + =, вы можете рассмотреть следующее:

  • Если ваши объекты неизменяемы, возможно, лучше вернуться по значению.
  • Если ваши объекты изменяемы, вероятно, лучше вернуться по ссылке.

Ответ 5

Обычно вы возвращаетесь по ссылке в операции, которая изменяет значение вещей, на которых он работает, например = или +=. Все остальные операции возвращаются по значению.

Это скорее эмпирическое правило. Вы можете проектировать своего оператора в любом случае.