Почему `&` (амперсанд) помещается перед некоторыми параметрами метода?
Интересно, почему перед NSError, например, ниже, мы помещаем: &error
, а не error
?
например.
NSArray *result = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
Надеюсь, вы сможете объяснить, также это всегда так или только в определенных ситуациях это необходимо? Спасибо.
Ответы
Ответ 1
Вам нужно взять адрес error
, потому что функция должна его изменить. error
передается указателем, поэтому вам нужен оператор "принять адрес" &
.
C и Objective-C передать параметры по значению. Если вы передадите error
без амперсанда, а метод, который вы вызываете, изменяет его, ваша функция, которая сделала вызов, не увидит никаких изменений, потому что метод будет работать с его локальной копией NSError*
.
Вы знаете, что вам нужен амперсанд перед соответствующим параметром, если вы посмотрите на подпись метода и посмотрите **
там:
- (NSArray *)executeFetchRequest:(NSFetchRequest *)request error:(NSError **)error
// ^ one ^^ two
Ответ 2
Тип параметра error
- (NSError **)
, то есть указатель на указатель на NSError. Переменная error
, которую вы используете в качестве аргумента, вероятно, объявлена как NSError *
, поэтому для правильного соответствия типов вам необходимо использовать адрес оператора, чтобы получить указатель на указатель (&error
), Причина, по которой методу требуется указатель на указатель в первую очередь, заключается в том, что он может изменить значение error
и получить это новое значение для вас, вызывающего метода.
Ответ 3
По сути, корень проблемы - это взлом за то, что он хочет вернуть второй (необязательный) объект.
Как мы можем это сделать, поскольку мы можем только вернуть одно? Ну, мы могли бы вернуть какой-то кортеж (return_value, error)
, но это немного громоздко. У нас может быть столько параметров, сколько нам нравится, можем ли мы что-то сделать с этими...
Таким образом, методы/функции не могут изменять свои параметры (точнее, они работают с копией, поэтому любые модификации, которые они делают, являются локальными). То есть (concurrency оставляет в стороне) значение fetchRequest
, прежде чем сообщение в вашем вопросе будет равно значению fetchRequest
. Обратите внимание, что объект, на который указывает fetchRequest
, может измениться, но значение fetchRequest
не будет.
Это немного связывает нас. Кроме того, подождите, мы знаем, что можем с радостью принять значение параметра и изменить то, на что оно указывает! Если вы посмотрите на объявление для executeFetchRequest:error:
, вы увидите, что он принимает значение NSError**
. Это "указатель на указатель на NSError
". Итак, мы можем инициализировать пустой/оборванный NSError*
, найти его адрес (с помощью унарного &
оператора) и передать это in. Затем этот метод может быть привязан к NSError*
, указанному этим.
Voila, у нас есть дополнительные дополнительные возвращаемые значения.