点符号与 - >之间的差异;在目标C中

时间:2011-11-14 18:30:04

标签: objective-c syntax pass-by-reference class-variables

我正在尝试在代码中使用尽可能少的内存。我尝试了两种方法将自定义类对象发送到方法。我不确定这两种方法之间是否有任何区别。假设我有两个类, Class1 Class2 ,每个类都有自己的类变量和方法。

所有代码均以 Class1

编写

方法1:

Class2 *class2Object = [[Class2 alloc] init];

[self doSomething: class2Object];

[class2Object release];

-(void) doSomething: (Class2 *) var {
int a = var.a;
}

方法2:

Class2 *class2Object = [[Class2 alloc] init];

[self doSomething: &class2Object];

[class2Object release];

-(void) doSomething: (Class2 **) var {
int a = var->a;
}

这两种方法之间是否有任何性能差异?第二种方法完全没有意义吗?为什么我可以在方法1中使用点符号,但必须使用 - >方法2?

感谢。

3 个答案:

答案 0 :(得分:4)

在方法1中,您正在访问名为a的属性。这看起来很好。

在方法2中,我对您的代码编译感到震惊。将指针传递给class2Object也毫无用处。将指针传递给对象的唯一原因是被调用的方法是否需要更新该参数(例如,如果它是一个out参数),这不是这里的情况。将指针传递给对象绝对不会影响内存使用。对象已经作为指针保存(这就是你编写Class2 *的原因),所以没有像在C ++中传递堆栈分配对象时看到的那样复制对象的开销(Obj-C没有这个概念)堆栈分配的对象,除了块,这是一个你不必担心的奇怪的角落情况。)

基本上,这里只需要使用方法1。

答案 1 :(得分:4)

  

这两种方法之间是否有任何性能差异?

实际上,性能差异可以忽略不计,因为在方法2中你还有一个间接(即指针解除引用,见下文);因此,方法1将为您节省几个时钟周期。

  

第二种方法完全没有意义吗?

方法2很有用,例如,当您想要分配类型为Class2的新实例并通过相同的参数将其传递回调用者时;说:

 - (bool)cloneObject:(Class2 **)var;

你传递一个物体;对象被克隆并返回var;因为它是对象本身的地址发生了变化,所以你需要有一个指向对象指针的指针来设置新地址;返回值仅表示操作是否正确执行。

当然,在这个例子中,做起来会更自然:

     - (Class2)cloneObject:(Class2*)var;

即,返回指向新分配对象的指针,但用例仍然存在。

  

为什么我可以在方法1中使用点符号,但必须使用 - >方法2?

在第二种情况下,你必须使用->,因为你没有直接处理指向对象的指针;你正在处理指向对象的指针;在这种情况下你需要做的是,首先,“取消引用”你的指针(即应用operator *),以获得指向对象的指针,然后像你一样访问后者;这可以写成:

 (*var).a

这里,var是指向Class2对象的指针; *var是取消引用它的结果,因此您有一个指向Class2对象的指针;最后,.a是访问对象属性的语法。语法:

var->a

只是上述操作的“简写”。

答案 2 :(得分:2)

C语法中的

x->y(*x).y相同,因此除了额外的(不必要的)指针获取和取消引用之外,它正在做什么没有区别,正如其他人所说的那样。但我想详细阐述一个更有趣的相关观点。

你应该理解

-(void) doSomething: (Class2 *) var {
   int a = var.a;
}

点是属性访问。 (它不能是结构字段访问,因为var是一个指针。)它完全等同于int a = [var a];(除非将getter明确设置为另一个方法)。

与所有方法调用一样,它将通过动态消息传递机制。如果你想避免轻微的开销,你可以直接访问变量。

如果属性a是从实例变量a合成的(可能已被称为其他内容,我们现在会说a),而不是通过属性访问变量,您可以将其公开(通过@public;否则实例变量默认受保护),然后通过->直接访问它:

-(void) doSomething: (Class2 *) var {
   int a = var->a;
}

(请注意,这与您所拥有的不同,因为var是对象指针本身,而不是指向指针的指针。)

但是,公共实例变量通常被认为是不好的风格而且不鼓励。使用它打破了面向对象编程中的抽象。为了完整起见,我将它提到这里,因为从技术上讲,它是访问实例变量的“最快”方法。