Еще одна проблема с вызовом по значению | ссылка
Вопрос прост и, возможно, обсуждался ранее, но я мог найти четкий ответ для своего случая. Предположим, я передаю объект-указатель в функцию
#include "foo.h"
int main()
{
foo * aFoo = new foo;
bar(aFoo);
delete aFoo;
aFoo = NULL;
return 0;
}
Тогда функция написана так
void bar (foo *f)
{
f->insert();
}
Вопрос:
Это call by value
или же call by reference
? Я знаю, что в вызове по значению есть издержки для копирования объекта из main() в bar(). Так что я хочу быть уверен, что это call by reference
,
2 ответа
Это вызов по значению, где значение указателя aFoo
копируется в параметр функции f
,
Вызов по ссылке - это вызов, в котором параметр является ссылкой, и побочные эффекты на аргумент (а не на объекты, на которые может указывать этот аргумент), возникающие внутри функции, видны вызывающей стороне, когда функция возвращается.
Так, например, это функция, принимающая параметр по ссылке:
void bar(foo*& f)
// ^
// Here you are taking a pointer by reference
Пока это функция, принимающая параметр по значению:
void bar(foo* f)
// ^
// Here you are taking a pointer to foo by value
Вы, вероятно, озадачены тем, что принимая foo
по ссылке и написанию:
void bar(foo& f)
{
f.insert();
}
Имеет почти такой же эффект, как и указатель на тот же foo
объект по значению и записи:
void bar(foo* f)
{ // Precondition: f != nullptr
f->insert();
}
Тем не менее, две вещи концептуально разные. Хотя значение / состояние объекта, который вы передали в первом случае, может отличаться, когда функция возвращается из значения / состояния, которое было у нее до вызова функции, во втором случае значение указателя, которое вы указали, будет таким же, как оно был до того как ты позвонил bar()
- в то время как объект, на который указывает указатель, мог измениться.
Также обратите внимание, что указатель может быть нулевым, а ссылка всегда привязана к объекту.
В вашем случае это call by value
с точки зрения указателя на Фу формально. Но так как вы передаете указатель на функцию вместо самого экземпляра класса, то он концептуально вызывается посредством ссылки в терминах экземпляра класса, поскольку вызов функции копирует не весь экземпляр, а только его указатель.
Foo fooInstance;
// providing a way to point (less formally you can call it refer) to the instance
Foo* fooPointer = &fooInstance;
// this function call is call by value (passing the value of the pointer).
// but you can logically view it as 'call by reference' to fooInstance.
bar(fooPointer);