В моей голове параметры функций всегда передаются по значению.Прохождение int
легко представить, пропуск double
просто больше, а пропуск struct
или class
действительно может быть очень большим.
Но, передав указатель на что-то, вы простоПередача адреса по значению. (Указатель часто является удобным размером для ЦП, как и int
.)
Ссылка очень похожа, и, конечно, я думаю о ссылке как о указателе, но с синтаксическим сахаром, чтобы он выглядел как объект, на который он ссылается, был передан по значению.
Вы также можете думать о ссылке как о const
указателе, то есть:
int i;
int j;
int* p = &i; // pointer to i
int* const cp = p; // cp points to i, but cp cannot be modified
p = &j; // OK - p is modified to point to j
*cp = 0; // OK - i is overwritten
cp = &j; // ERROR - cp cannot be modified
int& ri = i; // ri refers to i
ri = 1; // i is overwritten
ri = j; // i is overwritten again
// Did you think ri might refer to j?
Итак, указатель выполняет двойное время: это само по себе значение, но оно может также указывать на другое значение, когда вы разыменовываете его, например: *p
.
Кроме того, наличие ссылочных параметров означает, что вы не можетезаставьте их ссылаться на что-либо еще во время жизни функции, потому что нет способа выразить это.
Предполагается, что ссылка не может быть инициализирована с null
, но учтите это:
void foo(int& i);
int* p = 0;
foo(*p);
Это означает, что указатели должны быть проверены перед их использованием, но ссылки не могут быть проверены.Реализация foo()
может попытаться выполнить чтение или запись в i
, что приведет к нарушению доступа.
В приведенном выше примере указатель p
должен проверяться ранееиспользуется в вызове на foo
:
if (p) foo(*p);