ObjC属性和C运算符

时间:2014-05-01 21:59:30

标签: objective-c properties operators increment compound-assignment

给出以下属性声明:

@property NSInteger foo;

增量,减量和复合赋值运算符如何实际适用于self.foo

据我了解,self.foo仅仅是实际存取方法的语法糖。因此self.foo不能直接访问名为NSInteger的{​​{1}}变量,而是直接调用:

foo

- (void)setFoo:(NSInteger)foo;

然而,下面的一组代码非常好,没有标记,编译得很好,并且完全返回预期的结果:

- (NSInteger)foo;

而且我认为假设前后修复操作符以及其他9个复合操作符的递减将完全按照您在{{直接使用它们'时所期望的那样做,这可能是安全的。 {1}}变量。

如果self.foo = 0; NSLog(@"%d",self.foo); // prints 0 self.foo += 1; NSLog(@"%d",self.foo); // prints 1 self.foo++; NSLog(@"%d",self.foo); // prints 2 ++self.foo; NSLog(@"%d",self.foo); // prints 3 真的只是我上面提到的两种方法的语法糖,我就不明白为什么它会起作用。

如果我覆盖默认访问器以包含NSInteger语句,那么我可以看到每个语句被调用以及具有什么值,我可以看到首先调用getter然后调用setter。

这是否意味着以下内容:

self.foo

实际上被替换为:

NSLog

在预编译期间?


编辑:因此,在汇编级别,self.foo += 1; [self setFoo:([self foo] + 1)]; 之间是否存在差异?如果我们不是在谈论某个属性,并且self.foo += 1;只是一个常规的int,那么在self.foo = self.foo + 1;bar之间会有什么区别呢?

1 个答案:

答案 0 :(得分:6)

完全。你的假设是正确的。您可以自己实现属性并添加日志以再次检查您的假设

在@interface部分:

@property(nonatomic) NSInteger foo; 
     // nonatomic keyword is not really required but 
     // it is better to add it since we will implement 
     // property as nonatomic

在@implementation部分:

- (void)setFoo:(NSInteger)foo
{
    _foo = foo; // _foo variable is implicitly generated by compiler
    NSLog(@"set foo %d", _foo);
}

- (NSInteger)foo
{
    NSLog(@"get foo %d", _foo);
    return _foo;
}

然后运行

self.foo = 0;
self.foo += 1;

你应该在调试窗口中收到:

set foo 0
get foo 0
set foo 1

更新:

  • Re:“在汇编级别,self.foo += 1;self.foo = self.foo + 1;之间有什么区别吗?”

没有。两个[self setFoo:([self foo] + 1)];都会被调用。

  • Re:如果我们不是在讨论属性,而bar只是一个常规的int,那么在汇编级别,bar += 1;bar = bar + 1;之间会有区别吗?

是。但只有在关闭编译时优化时才会这样做。

bar += 1;更快。它将被编译为类似:

mov eax,dword ptr [bar]
inc eax                // difference is here!
mov dword ptr [bar],eax

bar = bar + 1;来:

mov eax,dword ptr [bar]
add eax,1              // difference is here!
mov dword ptr [bar],eax