void DoWork(int n);
void DoWork(const int &n);
Какая разница?
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);
когда вы используете параметр 'normal', вы передаете параметр по значению и, следовательно, создаете копию передаваемого параметра. если вы используете константную ссылку, вы передаете ее по ссылке и исходные данные не копируются.
в обоих случаях исходные данные не могут быть изменены изнутри функции.
EDIT:
В некоторых случаях исходные данные могут быть изменены в соответствии с Чарльзом Бейли в его ответе .
Важным отличием является то, что при передаче по ссылке 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
, тогда функция могла (даже если это не рекомендуется) изменить его значение с помощью cast.
например.
void DoWork(const int &n)
{
const_cast<int&>(n) = 22;
}
Это приведет к поведению undefined, если объект, переданный в действительности, был фактически const
.
Когда параметр передается по ссылке const, дополнительные затраты включают разыменование, худшую локальность объекта, меньшее количество возможностей для оптимизации компиляции.
Когда параметр передается по значению, а дополнительная стоимость - необходимость создания копии параметра. Обычно это вызывает беспокойство, когда тип объекта большой.
Есть три способа передать значения в функцию
Передать по значению
void f(int n){
n = n + 10;
}
int main(){
int x = 3;
f(x);
cout << x << endl;
}
Вывод: 3. Недостаток: когда параметр x
проходит через функцию f
, компилятор создает копию в памяти в формате x. Так что потеря памяти.
Передать по ссылке
void f(int& n){
n = n + 10;
}
int main(){
int x = 3;
f(x);
cout << x << endl;
}
Вывод: 13. Он устраняет недостаток передачи по значению, но если программист не хочет изменять значение, используйте ссылку на константу
Постоянная ссылка
void f(const int& n){
n = n + 10; // Error: assignment of read-only reference ‘n
}
int main(){
int x = 3;
f(x);
cout << x << endl;
}
Вывод: выдается ошибка в n = n + 10
, потому что, когда мы передаем аргумент константного ссылочного параметра, тогда это параметр только для чтения, вы не можете изменить значение n.
С
void DoWork(int n);
n
- это копия значения фактического параметра, и законно изменить значение n
внутри функции. С помощью
void DoWork(const int &n);
n
- это ссылка на фактический параметр, и нецелесообразно изменять его значение.
Так как никто из вас ничего не упоминал о ключевом слове const...
Ключевое слово const изменяет тип объявления типа или тип параметра функции, не изменяя значения. (Источник: MS)
Другими словами: передача параметра по ссылке подвергает его модификации вызываемым. Использование ключевого слова const предотвращает модификацию.
Первый метод передает n
по значению, т.е. в функцию отправляется копия n
. Второй передает n
по ссылке, что в основном означает, что указатель на n
, с которым вызвана функция, отправляется в функцию.
Для интегральных типов, таких как int
, нет смысла передавать в качестве ссылки на константу, поскольку размер ссылки обычно совпадает с размером ссылки (указателем). В случаях, когда изготовление копии стоит дорого, обычно лучше всего передавать по ссылке const.
Во-первых, не существует понятия cv-квалифицированных ссылок. Поэтому терминология "const reference" неверна и обычно используется для описания "ссылки на const". Лучше начать говорить о том, что имеется в виду.
$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
}