7

次のプロパティ宣言があるとします。

@property NSInteger foo;

インクリメント、デクリメント、および複合代入演算子は実際にどのように機能しself.fooますか?

self.foo実際のアクセサー メソッドの構文糖衣に過ぎないというのが私の理解でした。したがって、 という変数self.fooに直接アクセスするのではなく、次のいずれかを呼び出します。NSIntegerfoo

- (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そして、デクリメントのプレフィックス演算子とポストフィックス演算子、およびその他の 9 つの複合演算子は、変数に対して直接使用した場合に期待どおりの動作をすると想定するのがおそらく安全だと思います。

self.foo上記の2つの方法の構文糖衣が本当に機能する理由がわかりません。

デフォルトのアクセサーを上書きしてNSLogステートメントを含めると、それぞれがいつ呼び出され、どの値で呼び出されるかがわかります。ゲッターが最初に呼び出され、次にセッターが呼び出されることがわかります。

これは、次のことを意味しますか。

self.foo += 1;

効果的にこれに置き換えられます:

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

プリコンパイル中?


編集:では、アセンブリ レベルでは、 と の間に違いはself.foo += 1;ありself.foo = self.foo + 1;ますか? プロパティについて話しているのでbarはなく、単なる通常の int である場合、アセンブリ レベルで と の間に違いはbar += 1;ありbar = bar + 1;ますか?

4

1 に答える 1

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
于 2014-05-01T22:33:07.523 に答える