4

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

所有代码都写在Class1中

方法一:

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

[self doSomething: class2Object];

[class2Object release];

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

方法二:

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

[self doSomething: &class2Object];

[class2Object release];

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

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

谢谢。

4

3 回答 3

4

在方法 1 中,您正在访问一个名为a. 这看起来不错。

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

所以基本上,只要在这里使用方法 1。

于 2011-11-14T18:37:17.000 回答
4

这两种方法之间有什么性能差异吗?

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

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

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

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

你传入一个对象;对象被克隆并在 var 中返回;由于更改的是对象本身的地址,因此您需要有一个指向对象指针的指针才能设置新地址;返回值仅说明操作是否正确执行。

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

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

即,您将指针返回到新分配的对象,但用例仍然成立。

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

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

 (*var).a

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

var->a

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

于 2011-11-14T18:58:22.537 回答
2

x->y在 C 中的语法与 相同(*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是对象指针本身,而不是指向指针的指针。)

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

于 2011-11-14T23:38:46.373 回答