4.8 对象复制与传递
我们已经讨论了在Objective-C中如何创建类、如何创建类的实例(对象),以及类的继承等相关主题;接下来我们会讨论一些关于类和对象的应用问题。
■4.8.1 对象的复制
接下来,我们将继续使用CRobot类来演示对象的应用问题。首先,看下面的代码,我们会使用赋值运算符来复制对象。
CRobot *robot5 = [[CRobot alloc] init]; robot5.name = @"No.5"; CRobot *robot6 = [[CRobot alloc] init]; robot6 = robot5; NSLog(@"%@ , %@\n", robot5.name, robot6.name); // robot6.name = @"No.6"; NSLog(@"%@ , %@\n", robot5.name, robot6.name);
从代码执行的结果中,我们可以看到,第一个NSLog()函数显示“No.5 , No.5”。然后,当我们修改robot6.name的值以后,第二个NSLog()函数显示“No.6 , No.6”,也就是说,当我们修改robot6对象的值时,robot5对象的值也“变化”了,这是为什么呢?
实际上,我们说过,对象就是指针!当我们将一个对象赋值给另一个对象时,实际执行的是“浅复制”,也就是复制了对象的指针(引用),这样,代码中的robot5和robot6对象实际上是指向同一内存区域,也就是同一个对象体。所以,当我们修改其中一个对象的值时,实际会同时反映到两个对象的引用中。
如果我们需要完全复制一个全新的对象,即对象的“深复制”操作,有两个方法,一个方法是通过实现NSCopying协议,另一个方法就是通过归档来实现,稍后,我们会讨论相关内容。
■4.8.2 对象作为参数
我们已经看到对象在赋值时的默认表现,即进行浅复制,而这一特性在对象作为函数或方法的参数时也会有着相同的表现。通过对象向函数或方法传递数据时,实际上传递的是对象的引用,此时,在函数或方法中对这个对象的操作应该注意:
❑ 通过引用传递对象,可以提高数据的传递效率,因为只传递指针,而不需要复制全部数据。
❑ 在函数或方法中对于对象的修改,会直接反映到外部对象,应注意代码的目的是否确实是这样。
下面的代码,演示了CRobot对象作为函数参数的应用,大家可以在main.m文件中进行相关测试。首先是robotRename()函数,如下面的代码。
void robotRename(CRobot* robot) { if (robot ! = nil) robot.name = @"新的名字"; }
接下来,我们在main()函数中使用robotRename()函数,如下面的代码。
int main(int argc, const char * argv[]) { @autoreleasepool { CRobot *robot5 = [[CRobot alloc] init]; robot5.name = @"No.5"; robotRename(robot5); NSLog(robot5.name); } return 0; }