Кто-либо нашел потребность объявить возвращаемый параметр константы оператора присваивания копии?

Оператор присваивания копии имеет обычную подпись:

    my_class & operator = (my_class const & rhs);

Следующая подпись имеет какое-либо практическое применение?

    my_class const & operator = (my_class const & rhs);

Можно только определить один или другой, но не оба.

11
задан Keith M Smith 15 April 2010 в 21:20
поделиться

7 ответов

Основная причина, по которой возвращаемый тип присваивания копии является неконстантной ссылкой, заключается в том, что это требование стандарта для "Назначаемого".

Если вы сделаете возвращаемый тип ссылкой const , то ваш класс не будет соответствовать требованиям для использования ни в одном из стандартных библиотечных контейнеров.

20
ответ дан 3 December 2019 в 02:01
поделиться

Ответ, который отражает ответ из Перегрузка оператора присваивания в C ++ :

Возврат const & все равно разрешить цепочку присваивания:

a = b = c;

Но запретит некоторые из наиболее необычных применений:

(a = b) = c;

Обратите внимание, что это делает семантику оператора присваивания аналогичной той, что он имеет в C, где значение, возвращаемое = оператор не является lvalue. В C ++ стандарт изменил его, поэтому оператор = возвращает тип левого операнда, поэтому результатом является lvalue. Но , как заметил Стив Джессоп в комментарии к другому ответу , хотя это позволяет компилятору принимать

(a = b) = c;

даже для встроенных модулей, результатом является неопределенное поведение для встроенных модулей, поскольку a изменяется дважды без промежуточной точки последовательности. Этой проблемы можно избежать для не встроенных функций с помощью operator = () , потому что вызов функции operator = () служит точкой последовательности.

Я не вижу проблем с возвратом const & , если только вы не хотите специально разрешить семантику lvalue (и спроектировать класс так, чтобы он действовал разумно с этой семантикой). Если вы, пользователи, хотите сделать что-то необычное с результатом operator = () , я бы предпочел, чтобы класс запретил это, а не надеялся, что он сделает все правильно случайно, а не разработкой.

Также. обратите внимание, что в то время как вы сказали:

Вы можете определить только одно или другое, но не оба.

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

my_class& operator=( my_class& rhs);
my_class const& operator=(my_class const& rhs);

Я не совсем уверен, что это вам даст. Присваиваемый объект (предположительно возвращаемая ссылка) не является константой в обоих случаях, поэтому нет логической причины возвращать const & только потому, что правая сторона = равно const . Но, может быть, я что-то упускаю ...

4
ответ дан 3 December 2019 в 02:01
поделиться

Эффективный C ++ объясняет, что это нарушит совместимость со встроенными типами C ++.

Вы можете сделать это с помощью простого int s:

(x = y) = z;

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

Этот пример есть во 2-м издании, но его больше нет в 3-м. Тем не менее, эта цитата из 3-го изд., Пункт 10 говорит о том же:

[...] присвоение возвращает ссылку на его левый аргумент, и это соглашение, которому вы должны следовать при реализации операторов присваивания для своих классов:

class Widget {
public:
  ...
  Widget& operator=(const Widget& rhs)   // return type is a reference to
  {                                      // the current class
  ...
  return *this;                        // return the left-hand object
  }
  ...
};
3
ответ дан 3 December 2019 в 02:01
поделиться

Почему все одержимы (a = b) = c ? Было ли это когда-нибудь написано случайно?

Вероятно, есть некоторая непредвиденная полезность изменения результата присваивания. Вы не просто устанавливаете произвольные правила против выдуманных примеров, которые выглядят забавно. Семантически нет причин, по которым он должен быть const , поэтому не объявляйте его const для лексических побочных эффектов.

Вот пример довольно разумного кода, который нарушает присваивание const & :

my_class &ref = a = b;
2
ответ дан 3 December 2019 в 02:01
поделиться

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

0
ответ дан 3 December 2019 в 02:01
поделиться

Да, это должно быть const . В противном случае клиенты могут сделать это:

class MyClass
{
public:
      MyClass & operator = (MyClass const & rhs);
}

void Foo() {
    MyClass a, b, c;
    (a = b) = c; //Yikes!
}
-1
ответ дан 3 December 2019 в 02:01
поделиться

Не делайте этого. Это не позволяет клиенту писать что-то вроде:

(a = b).non_const_method();

вместо более длинной формы:

a = b;
a.non_const_method();

Хотя вам может не понравиться сокращенный стиль, на самом деле пользователю библиотеки решать, как он хочет писать код.

7
ответ дан 3 December 2019 в 02:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: