Почему передача ссылкой константы вместо значением?

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

Править: Таким образом в основном передающий ссылкой константы старается не копировать объект. Таким образом в том, какие ситуации копируют объектную пользу? Я имею в виду, почему не только используют ссылки константы все время, если это оптимизирует производительность все время?

45
задан Maulrus 6 April 2010 в 05:32
поделиться

7 ответов

Есть два основных соображения. Первое - это затраты на копирование переданного объекта, а второе - предположения, которые компилятор может сделать, если объект является локальным объектом.

Например, в первой форме, в теле f нельзя предположить, что a и b не ссылаются на один и тот же объект; поэтому значение a должно быть перечитано после любой записи в b, на всякий случай. Во второй форме a не может быть изменено через запись в b, так как оно локально для функции, поэтому повторные чтения не нужны.

void f(const Obj& a, Obj& b)
{
    // a and b could reference the same object
}

void f(Obj a, Obj& b)
{
    // a is local, b cannot be a reference to a
}

Например: В первом примере компилятор может предположить, что значение локального объекта не изменится при несвязанном вызове. Без информации о h компилятор не может знать, не изменяется ли объект, на который эта функция имеет ссылку (через параметр ссылки), при h. Например, этот объект может быть частью глобального состояния, которое изменяется h.

void g(const Obj& a)
{
    // ...
    h(); // the value of a might change
    // ...
}

void g(Obj a)
{
    // ...
    h(); // the value of a is unlikely to change
    // ...
}

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

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

51
ответ дан 26 November 2019 в 21:13
поделиться

В некоторых случаях создание копии объекта может сильно повлиять на производительность. Рассмотрим функцию, аргумент которой будет std :: vector , и вы хотите передать вектор с 1 миллионом элементов. В этом случае вы захотите использовать ссылку на константу вместо передачи по значению. В этом SO-вопросе вы можете найти простое общее правило для вашего вопроса.

4
ответ дан 26 November 2019 в 21:13
поделиться

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

Обычно основные типы ( int , double , ...) передаются по значению, а типы классов передаются по константной ссылке.

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

22
ответ дан 26 November 2019 в 21:13
поделиться

Из-за повышения производительности, которое вы получите. Допустим, у вас есть большой объект (с точки зрения размера в байтах). Теперь, если вы передадите этот объект по значению функции, необходимо создать ненужную копию this, однако вы можете получить тот же эффект, передав ссылку const на сам объект без создания копии. Поскольку ссылка обычно хранится в виде указателя под капотами, стоимость передачи ссылки составляет всего sizeof (pointer) .

2
ответ дан 26 November 2019 в 21:13
поделиться

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

Возможно, объект нельзя скопировать, и ваш выбор ограничен.

2
ответ дан 26 November 2019 в 21:13
поделиться

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

2
ответ дан 26 November 2019 в 21:13
поделиться

Чтобы избежать создания ненужной копии , тем самым улучшая производительность.

2
ответ дан 26 November 2019 в 21:13
поделиться
Другие вопросы по тегам:

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