ObjC 属性和 C 运算符

Posted

技术标签:

【中文标题】ObjC 属性和 C 运算符【英文标题】:ObjC properties and C operators 【发布时间】:2014-06-18 12:03:35 【问题描述】:

给定以下属性声明:

@property NSInteger foo;

递增、递减和复合赋值运算符实际上是如何在self.foo 上工作的?

据我了解,self.foo 只是实际访问器方法的语法糖。所以self.foo 不是直接访问一个名为fooNSInteger 变量,而是调用其中一个:

- (void)setFoo:(NSInteger)foo;

- (NSInteger)foo;

然而,以下代码集非常好,没有标记,编译正常,并且完全返回了预期的结果:

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 变量上使用它们,那么假设递减 pre 和 post fix 运算符以及其他 9 个复合运算符将完全符合您的预期,这可能是安全的。

如果self.foo 真的只是我上面提到的两种方法的语法糖,我只是不明白为什么它会起作用。

如果我覆盖默认访问器以包含 NSLog 语句,以便我可以查看每个语句的调用时间和值,我可以看到先调用 getter,然后调用 setter。

这是否意味着:

self.foo += 1;

实际上被替换为:

[self setFoo:([self foo] + 1)];

在预编译期间?


编辑:那么,在汇编级别,self.foo += 1;self.foo = self.foo + 1; 之间有什么区别吗?如果我们不是在谈论属性,而bar 只是一个常规的 int,那么在汇编级别,bar += 1;bar = bar + 1; 之间是否有区别?

【问题讨论】:

没错。你的假设是正确的。 鉴于结果,很明显您的假设是正确的。 我在我的问题中添加了一个附录,试图澄清我的实际意思。 @nhgrif 我已将您的问题的答案添加到我的帖子中。请检查。 【参考方案1】:

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

在您的@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

更新:

回复:“在汇编级别,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

【讨论】:

因此,如果您期望复合运算符的行为与在其他语言中的行为相同,那么复合运算符对 Objective-C 属性有点误导。我可以假设具有递增/递减运算符的非属性具有相同的装配差异吗? @nhgrif 不确定我是否理解正确。你能澄清你的问题吗? self.someVar++someVar++++self.someVar++someVar 以及减号。 @nhgrif 是的,他们都有相同的行为。

以上是关于ObjC 属性和 C 运算符的主要内容,如果未能解决你的问题,请参考以下文章

Python入门-6面向对象编程:10特殊方法和运算符重载-特殊属性

jquery复选框选中的属性和三元运算符[重复]

第四章----关系代数运算

c ++:原始指针映射中的复制,删除和运算符=

二级C语言知识!高手请教!

JAVA怎样重载操作符?