Передача C++ ссылкой константы и возврат ссылкой константы

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

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

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

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

Действительно ли это допустимо для возврата a const ссылка? Кроме того, мог кто-то говорить мне: действительно ли это выгодно?

11
задан Kiril 9 July 2010 в 22:29
поделиться

5 ответов

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

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

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

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

9
ответ дан 3 December 2019 в 03:34
поделиться

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

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

6
ответ дан 3 December 2019 в 03:34
поделиться

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

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

3
ответ дан 3 December 2019 в 03:34
поделиться

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

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

8
ответ дан 3 December 2019 в 03:34
поделиться

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

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

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

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

Итак, я бы не стал заниматься этим, и каждый может бросить мне вызов.

1
ответ дан 3 December 2019 в 03:34
поделиться
Другие вопросы по тегам:

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