【问题标题】:Objective-C passing object to function is always by reference or or by value?Objective-C 将对象传递给函数总是通过引用还是通过值?
【发布时间】:2016-08-30 05:43:55
【问题描述】:

在 Objective-c 中,我将 NSMutableDictionary 传递给函数并在函数内部对其进行修改,它返回修改后的可变字典:

NSMutableDictionary *obj2 = [[NSMutableDictionary alloc]initWithObjectsAndKeys:@"hello",@"fname",nil];
[self callerDictionary:obj2];
NSLog(@"%@",obj2[@"fname"]);//printing "Hi"
-(void)callerDictionary:(NSMutableDictionary*)obj
{
    obj[@"fname"] = @"Hi";   
}

【问题讨论】:

  • 字典不是数组。
  • 我已经编辑了我的问题,先生

标签: ios objective-c


【解决方案1】:

从技术上讲,Objective C 总是按值传递参数,就像 C 一样,但实际上,当你传递一个对象时,你需要传递一个指针。虽然这个指针是按值传递的,但 Objective-C 的语义给出了与传递对象 reference 相同的效果;如果您修改指针指向的对象,那么您正在修改调用上下文中指向的相同对象实例。 Objective C 编程中使用的常用术语是“对象引用”,尽管它实际上是一个指针值。

从方法签名中的*可以看出,它是一个指针(或者常用的对象引用)。如果您传递的是内部类型,例如 int,那么除非您明确声明该方法需要引用,否则它将按值传递:

例如:

-(void) someFunction:(int *)intPointer {
    *intPointer = 5;
}

将被称为

int someInteger = 0;

[self someFunction: &someInteger];

// someInteger is now 5

与使用真正引用的 Swift 相比,可以看出指针值和真正的对象引用之间的区别;

如果我有

-(void)someFunction:(NSString *)someString {
     int length = [someString length];
}

然后做

NSMutableArray *array = [NSMutableArray new];
[someFunction: (NSString *)array];

我会得到一个运行时异常,因为数组没有length 方法,但是编译器无法确认我传递的类型,因为它是一个指针。

如果我在 Swift 中尝试了等价的操作,那么我会得到一个编译时错误,因为它知道类型强制总是会失败

【讨论】:

  • stackoverflow.com/questions/22213197/… 在这个问题中说它总是按值传递
  • 好吧,在我看来,那个人有点迂腐。没错,它传递的是一个指针值,而不是真正的引用,但在语义上它具有相同的效果;对指针指向的对象的修改会反映在调用上下文中,因为函数中的指针与调用上下文中的指针指向内存中的相同对象。在 C 中,您使用术语“指针”,而在面向对象的语言(例如 Objective-C)中,您使用术语“对象引用”或仅使用“引用”
  • 这并不过分迂腐,因为了解对象引用和指向非对象类型的指针之间的区别很重要。对象引用被隐式取消引用,而指向其他类型的指针则没有。
  • 是的,但 Objective C 的语法本质上隐藏了这种取消引用。对于大多数人来说,引用/价值的问题归结为函数/方法中副作用的可能性;在 Objective-C 中使用指针作为“对象引用”意味着会产生副作用。无论您输入NSString 还是NSString * 都只是语法细节
【解决方案2】:

Objective C 中的所有对象都通过引用传递。 NSUInteger、double等所有C类型都按值传递

【讨论】:

  • stackoverflow.com/questions/22213197/… ..如果你通过这个答案是说每件事都是按价值传递的
  • 所有对象都通过引用(指针)访问。但是,引用是按值传递的。
  • 标记指针实例是按值传递的(但这实际上是一个不影响开发者体验的实现细节)。
【解决方案3】:

C 和 Objective-C 总是按值传递参数。 Objective-C 对象总是通过引用(即指针)访问。变量类型(int、指针等)和变量作为函数参数传递的方式是有区别的。在这两种情况下使用术语 reference 可能会引起混淆。

按价值计算:

void f(int a) {
    a = 14;
}

int a = 5;

NSLog(@"%d", a);  // prints: 5

f(a);

NSLog(@"%d", a);  // prints: 5

两次都打印了值 5,因为函数 f() 被赋予了 a 值的 副本,即 5。函数中引用的变量不是同一个变量传入的;这是一个副本。

在 C++ 中,您可以拥有通过引用获取参数的函数。

参考:

void f(int &a) {
    a = 14;
}

int a = 5;

NSLog(@"%d", a);  // prints: 5

f(a);

NSLog(@"%d", a);  // prints: 14

注意函数签名中的&。在 C++(但不是 C,也不是 Objective-C)中,这意味着参数是通过引用传递的。这意味着对a 的引用(指针)被传递给函数。在函数内部,a 变量被隐式解引用(记住,它确实是一个指针,但你不要把它当作一个指针),并且原来在函数外部声明的a 变量被改变了。

在 C 和 Objective-C 中,将指针传递给函数在功能上等同于在 C++ 中使用引用参数。这是因为将地址的副本提供给函数(请记住,参数仍然按值传递),并且该地址指向与原始指针相同的对象实例。您在函数中看不到任何显式指针取消引用(类似于 C++ 引用)的原因是因为用于对象访问的 Objective-C 语法总是隐式取消引用——在函数中不会改变这种行为。

【讨论】:

  • 标记指针实例是严格按值传递的对象,但它们是只读的,因此几乎是无关紧要的琐事。
猜你喜欢
  • 1970-01-01
  • 2020-04-01
  • 2014-12-26
  • 2014-07-26
  • 2017-01-27
  • 2012-02-03
  • 2018-06-20
  • 2012-03-15
  • 2015-06-12
相关资源
最近更新 更多