Параметр оператора присваивания должен быть ссылочным? - PullRequest
6 голосов
/ 31 мая 2010

При перегрузке оператора присваивания класса в C ++ его параметр должен быть ссылкой?

Например,

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

Может ли это быть

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

Спасибо!

Ответы [ 5 ]

9 голосов
/ 31 мая 2010

Параметр перегруженного оператора присваивания может быть любого типа, и его можно передавать по ссылке или по значению (ну, если тип не является копируемым, то он не может быть передан по значению, очевидно). *

Так, например, у вас может быть оператор присваивания, который принимает int в качестве параметра:

MyClass& operator=(int);

Оператор присваивания копии является частным случаем оператора присваивания. Это любой оператор присваивания, который принимает тот же тип, что и класс, либо по значению, либо по ссылке (ссылка может быть константной или изменчивой).

Если вы явно не реализуете какую-то форму оператора присваивания копии, тогда он неявно объявляется и реализуется компилятором.

5 голосов
/ 31 мая 2010

Рекомендации по перегрузке операторов C ++ предполагают, что оператор присваивания получает константную ссылку. Согласно сайту, причина в том, что мы не хотим менять аргумент (начиная с const), а просто левую часть оператора. Таким образом, это экономит время, чтобы передать его по ссылке.

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

5 голосов
/ 31 мая 2010

Как правило, вам решать, нет необходимости . Первый вариант является общим и «каноническим» и подходит для любой реализации оператора присваивания.

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

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

3 голосов
/ 31 мая 2010

Знаете ли вы идиому copy и swap для безопасного назначения исключений?

MyClass& operator=(const MyClass& rhs)
{
    MyClass copy(rhs);
    swap(copy);
    return *this;
}

Реализация может быть упрощена (а в некоторых случаях ускорена) с помощью вызова по значению:

MyClass& operator=(MyClass copy)
{
    swap(copy);
    return *this;
}
0 голосов
/ 01 марта 2014

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

Вы можете передать по значению, в этом нет ничего плохого. (как вы показали в своем вопросе.)

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

Это экономит время обработки, особенно если это что-то большое с тысячами имен ... В этом случае сэкономленное время будет почти ничем.

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

...