void DoWork(int n);
void DoWork(const int &n);
Какая разница?
Разница более заметна, когда вы передаете большую структуру / класс.
struct MyData {
int a,b,c,d,e,f,g,h;
long array[1234];
};
void DoWork(MyData md);
void DoWork(const MyData& md);
когда вы используете «нормальный» параметр, вы передаете параметр по значению и, следовательно, создаете копию переданного вами параметра. если вы используете константную ссылку, вы передаете ее по ссылке, и исходные данные не копируются.
в обоих случаях исходные данные не могут быть изменены изнутри функции.
РЕДАКТИРОВАТЬ:
В некоторых случаях исходные данные могут быть изменены, как указано Чарльзом Бейли в его ответе .
Важное отличие состоит в том, что при передаче по ссылке const
новый объект не создается. В теле функции параметр фактически является псевдонимом для переданного объекта.
Поскольку ссылка является ссылкой const
, тело функции не может напрямую изменять значение этого объекта. Это имеет свойство, аналогичное передаче по значению, когда тело функции также не может изменить значение переданного объекта, в данном случае потому, что параметр является копией.
Есть принципиальные различия.Если параметр является ссылкой const
, но переданный объект на самом деле не был const
, то значение объекта может быть изменено во время самого вызова функции.
Например.
int a;
void DoWork(const int &n)
{
a = n * 2; // If n was a reference to a, n will have been doubled
f(); // Might change the value of whatever n refers to
}
int main()
{
DoWork(a);
}
Также, если переданный объект на самом деле не был const
, тогда функция могла бы (даже если это не рекомендуется) изменить свое значение с помощью преобразования.
например.
void DoWork(const int &n)
{
const_cast<int&>(n) = 22;
}
Это привело бы к неопределенному поведению, если бы переданный объект был на самом деле const
.
Когда параметр передается по константной ссылке, дополнительные затраты включают разыменование, худшую локальность объекта, меньшие возможности для оптимизации компиляции.
Когда параметр передается по значению и за дополнительную плату необходимо создать копию параметра. Обычно это вызывает беспокойство только тогда, когда тип объекта большой.
Поскольку никто из вас ничего не упомянул о ключевом слове const ...
Ключевое слово const изменяет тип объявления типа или тип параметра функции, предотвращая изменение значения. (Источник: MS)
Другими словами: передача параметра по ссылке делает его доступным для модификации вызываемым объектом. Использование ключевого слова const предотвращает изменение.
С
void DoWork(int n);
n
является копией значения фактического параметра, и изменение значения n является допустимым.
внутри функции. С
void DoWork(const int &n);
n
является ссылкой на фактический параметр, и изменение его значения является незаконным.
Первый метод передает n
по значению, т.е. копия n
отправляется функции. Второй передает n
по ссылке, что в основном означает, что указатель на n
, с которым вызывается функция, отправляется в функцию.
Для целочисленных типов, таких как int
, нет смысла передавать как константную ссылку, поскольку размер ссылки обычно такой же, как размер ссылки (указателя). В случаях, когда создание копии обходится дорого, обычно лучше использовать константную ссылку.
Во-первых, не существует концепции ссылок с уточнением cv. Таким образом, термин «ссылка на константу» неверен и обычно используется для описания «ссылки на константу». Лучше начать говорить о том, что имеется в виду.
$8.3.2/1- "Ссылки с квалификацией Cv имеют неправильный формат, за исключением случаев, когда квалификаторы cv вводятся с помощью typedef (7.1.3) или аргумента типа шаблона (14.3), и в этом случае квалификаторы cv игнорируются."
Вот различия
$13.1 - "Только константные и изменчивые спецификаторы типов на самом внешнем уровень спецификации типа параметра таким образом игнорируется; const и volatile спецификаторы типов, спрятанные внутри типа параметра спецификации являются важными и могут быть использованы для различения объявления перегруженных функций.112). В частности, для любого типа T «указатель на T», «указатель на const T» и «указатель на volatile T» считаются отдельными типами параметров, как и «ссылка на T», «ссылка на const T» и «ссылка на volatile T».
void f(int &n){
cout << 1;
n++;
}
void f(int const &n){
cout << 2;
//n++; // Error!, Non modifiable lvalue
}
int main(){
int x = 2;
f(x); // Calls overload 1, after the call x is 3
f(2); // Calls overload 2
f(2.2); // Calls overload 2, a temporary of double is created $8.5/3
}