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

С++ Pass By Const Reference и Return By Const Reference

Я пытаюсь понять, есть ли какая-либо польза для возврата ссылки const. У меня есть факториальная функция, которая обычно выглядит так:

unsigned long factorial(unsigned long n)
{
    return (n == 0) ? 1 : n * factorial(n - 1);
}

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

const unsigned long & factorial(const unsigned long& n)
{
    return (n == 0) ? 1 : n * factorial(n - 1);
}

Можно ли вернуть ссылку const? Кроме того, может кто-нибудь, пожалуйста, скажите мне: полезно ли?

4b9b3361

Ответ 1

Это неверно. Вы не можете вернуть ссылку на локальную переменную.

Компилятор MSVS С++ даже дает следующее предупреждение:

main.cc : warning C4172: returning address of local variable or temporary

Не совсем уверен в GCC, но, вероятно, результат будет таким же.

Ответ 2

Ссылка на константу не быстрее, чем значение, если размер значения мал. В этом случае тип значения long, который является небольшим IMO (например, от 4 до 8 байтов): так что ссылка const будет не быстрее. На самом деле это может быть медленнее, потому что для получения значения ссылки компилятору может потребоваться исправить код, который будет разыменовывать ссылку (например, разыменование указателя).

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

Ответ 3

Ссылка на константу здесь неверна - вы возвращаете ссылку на локальную переменную - неименованный временной здесь, либо 1, либо результат n * factorial(n - 1). Поскольку ссылка ссылается на локальную переменную в функции, к моменту обращения ссылки к вызывающей стороне эта локальная переменная уже вышла из области видимости и недействительна.

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

Ответ 4

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

* ПРИМЕЧАНИЕ. В вашем случае возвращаемый вами элемент является локальной переменной и, следовательно, не переживет вызов функции. Следовательно, код, который вы предоставили, вызывает гнусное поведение undefined.

Ответ 5

Возможно, я никогда этого не сделаю. Почему?

Потому что это хороший способ сделать ваш код нечитаемым.

Кроме того, компилятор будет оптимизировать без этого взлома.

И кроме того, разве у вас нет других "узких мест" для оптимизации в вашей программе?
Я имею в виду, что если вы возьмете эту часть своего кода и посмотрите на нее в сборке, вы увидите, что передача функции значение и получение результата - это всего лишь несколько кодов операций. Как?
Ну, 32-битное целое будет вписываться в регистр. Быстро, как "mov eax,...".
С другой стороны, у вас, вероятно, есть другие проблемы с дизайном/алгоритмом, которые могут быть оптимизированы... Если это не так просто, как программа "привет мир".

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