я прочитал праймер C ++ 5-й. я видел, что это нормально, когда мы используем нереферентные параметры в операторах присваивания, которые используют копирование и своп, но в других операторах присваивания мы всегда используем опорные параметры и копируем правый операнд перед уничтожением левого операнда, чтобы убедиться, что операторы присваивания работают правильно, если объект назначен самому себе. почему бы не использовать параметр без ссылки в операторах присваивания, которые будут копироваться в теле функции позже, чтобы нам не нужно было копировать правый операнд в теле функции?
Операторы назначения копирования обычно должны принимать свой параметр по значению (а не по ссылке), чтобы выполнить копирование и обмен с использованием параметра по значению в качестве копии.
Если вы не делаете (просто) копирование и обмен, тогда, возможно, ваш оператор копирования должен взять свой параметр по ссылке. Что касается того, почему вы не будете делать копирование и обмен: вероятно, из-за некоторой специфической оптимизации для типа. Рассмотрим для примера std::array
тривиально копируемого типа (тривиально, чтобы избежать разговоров о безопасности исключений). Наиболее эффективным из возможных назначений является непосредственное копирование байтов: вам не нужна временная копия объекта и, конечно же, вам не нужен обмен. Так что на практике вы бы взяли ваш параметр по ссылке, напишите std::copy
и ожидаем, что компилятор сделает это оптимально.
Самостоятельное назначение в специальном регистре в операторе копирования иногда встречается в учебниках даже с копированием и заменой, но в C ++ 03 это вообще плохая идея. Несмотря на то, что он оптимизирует случай самопредставления, параметр by-reference де-оптимизирует случай назначения из временного. В C ++ 11 это менее очевидно плохо, потому что случай назначения из временного объекта может обрабатываться оператором присваивания перемещения вместо оператора присваивания копии. Но это, вероятно, все еще не нужно. Самопредставление в реальном коде встречается довольно редко, поэтому может даже оказаться, что сравнение указателей в общем случае составляет Больше время выполнения, чем копия в редком случае.
Я не читал 5-е издание «Учебника по С ++», и вы решили не показывать код, о котором вы спрашиваете, поэтому я не могу комментировать конкретные случаи, когда он дает операторы присваивания (копирование присваивания или в противном случае), которые принимают параметры по ссылке.
Извините, но в целом я думаю, что статистически более вероятно, что вы запутались, чем книга 😉 Вы говорите:
… в операторах присваивания, которые используют копирование и обмен, но в других операторах присваивания
Итак, «другие операторы присваивания» — это операторы присваивания, которые не использовать копирование и обмен?
мы всегда используем ссылочные параметры и копируем правый операнд перед уничтожением
левый операнд
Если вы копируете правый операнд, то вы являются делать копирование и обмен. Или, по крайней мере, вы очень близки к этому, потому что, сделав копию, нет смысла использовать что-либо, кроме свопа, чтобы получить копию в левой части. В любом случае, если первое, что делает функция, это копирует параметр по ссылке, то он должен был принять параметр по значению.
чтобы убедиться, что операторы присваивания работают правильно, если объект назначен самому себе
Если ваш метод обеспечения правильного самоназначения заключается в том, чтобы всегда копировать правый операнд, тогда вы должны принимать параметр по значению. Больше ничего не нужно. Однако существуют и другие методики обеспечения самостоятельной работы. Возможно, что-то подобное происходит в коде, который вы не показываете.
Основная причина — эффективность. Для небольшого класса / структуры это, вероятно, не имеет значения, но если это большой сложный класс, это другой вопрос. Если вы передадите по значению, вы будете вызывать потенциально большую и сложную операцию копирования. Это может потребовать большого выделения памяти, возможно.
Реальный ответ заключается в том, что иногда это не имеет значения. Часто это действительно имеет значение, и поэтому лучший подход состоит в том, чтобы просто всегда использовать ссылку.