【问题标题】:Difference Between Dot Notation and -> in Objective CObjective C中点符号和->之间的区别
【发布时间】:2011-12-28 21:43:04
【问题描述】:

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

所有代码都写在Class1

方法一:

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;
}

这两种方法在性能上有区别吗?第二种方法完全没有意义吗?为什么我可以在方法一中使用点符号,但在方法二中必须使用->?

谢谢。

【问题讨论】:

  • Objective-C 中没有类变量这样的东西。

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


【解决方案1】:

C 语法中的x->y(*x).y 相同,因此正如其他人所说,除了额外的(不必要的)指针获取和取消引用之外,它的作用没有任何区别。但我想详细说明一个更有趣的相关点。

你应该明白

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

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

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

如果属性 a 是从实例变量 a 合成的(可以称为其他名称,我们现在将说 a),而不是通过属性访问该变量,您可以改为将其声明为 public (通过@public;否则默认保护实例变量),然后直接通过->访问:

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

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

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

【讨论】:

    【解决方案2】:

    这两种方法在性能上有区别吗?

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

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

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

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

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

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

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

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

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

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

     (*var).a
    

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

    var->a
    

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

    【讨论】:

    • 感谢您的详细回复!绝对可以解决问题。
    【解决方案3】:

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

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

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

    【讨论】:

    • 好的,所以如果我在 doSomething 中更新 var.a 的值,那么方法 2 是否可以按原样使用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-02
    • 1970-01-01
    • 1970-01-01
    • 2012-05-07
    • 1970-01-01
    • 2010-12-10
    • 1970-01-01
    相关资源
    最近更新 更多