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

Почему я должен когда-либо возвращать что-то по значению, поскольку С++ содержит ссылки const?

Рассмотрим эту функцию:

Thing func(){
    return something;
}

Каждый вызов этой функции, копия something производится и передается вызывающему.

Мой вопрос: почему бы не просто сделать это (каждый раз, когда я хочу что-то вернуть по значению)?

const Thing& func(){
    return something;
}

Таким образом, мы не рискуем копировать something без повода для этого. Если клиенту нужно только "читать" из something, но не "писать" ему, ссылка на const может сделать именно это. И если клиенту нужна копия, он может просто назначить ссылку на константу переменной, например:

Thing thing = func(); // the object is passed by const reference, and then copied.

Так есть ли когда-либо причина просто вернуться по значению?

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


Последующий вопрос: читая ответы, я понимаю, что для каждого метода есть плюсы и минусы. Есть ли по умолчанию? Например. msgstr "по умолчанию возврат по значению"? Или это чисто основано на конкретном случае?

4b9b3361

Ответ 1

Потому что, если ваш объект (по какой-либо причине) был создан в стек вызываемой функции, возвращение и использование ссылки на него - это поведение undefined.

С возвратом по значению компилятор иногда может оптимизировать возврат и нет опасных ссылок. С С++ 11 и перемещением семантики это выводится на новый уровень.

Не имеет смысла говорить "всегда лучше возвращаться по ссылке, а не по значению", каждый случай, когда он используется, должен рассматриваться отдельно.

Ответ 2

Так есть ли когда-либо причина просто вернуться по значению?

Да. Если вы возвращаете локальную переменную функции, например.

int compute(int a, int b)
{
    int result;
    // a lot of magic
    return result;
}

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

Кроме того, возвращаемые функции локальные переменные с типом класса "по значению" могут быть оптимизированы с помощью копирования elision - имя оптимизации NRVO. И если эта оптимизация не применяется, новая введенная семантика перемещения может (хотя вы должны просто полагаться на copy elision, она работает очень хорошо). В таких случаях нет стимула возвращать ссылку.

Кроме того, вы не захотите возвращать ссылки, если хотите сохранить личные вещи. Зачем вам возвращать константную ссылку на переменную частного члена в публичной функции-члене? Он указывает, что существует переменная-член, информация, которую сайт вызова не должен знать. Также обратите внимание на безопасность потоков. Возвращаемые переменные по ссылке могут привести к гонке данных, если один и тот же объект будет изменен другим потоком после return -statement.


Или это чисто основано на конкретном случае?

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

* И также, только если им действительно нужно.

Ответ 3

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

Если вы возвращаете что-то постоянное, тогда вы правы; обычно лучше вернуть ссылку и позволить вызывающему абоненту решить, следует ли ее копировать. Но могут быть и другие причины, такие как безопасность потоков, которые предпочитают возвращать значение даже тогда: возвращая копию, читатель не может получить доступ к постоянному объекту, а другой поток может его изменить.