4

我最近一直在学习现代 Objective-C,并开始使用美妙的新语法来处理NSNumber文字。阅读后实际上有两种创建NSNumbers 的方法:

// NSNumber literal
NSNumber *a = @42;

// Boxed expression
NSNumber *a = @(42);    

最终结果是相同的(两者都生成NSNumber一个值为 42 的值),但是有什么理由在装箱表达式上使用文字来表示简单的数字常量?

我可以看到两个喜欢盒装表达式的风格原因:

  1. 更容易在视觉上解析,特别是如果数字为负数或宏(Xcode 语法突出显示不正确地着色@-1@INT_MAX)。
  2. 如果需要,以后更容易更改为非常量表达式,而无需添加括号。类似于为“未来证明”添加大括号到单行 if 语句的论点。

但是有任何负面或理由坚持字面意思吗?Clang 页面在盒装表达式部分中没有提及任何表明性能损失或其他负面影响的内容。

那么在这些简单的数字常量的情况下,这只是一种风格吗?

4

2 回答 2

5

这些实际上编译为相同的程序集:

NSNumber *value = @42;
NSNumber *otherValue = @(42);

这导致以下优化的装配:

    // NSNumber *value = @42;

movl    L_OBJC_CLASSLIST_REFERENCES_$_-L0$pb(%edi), %eax <-- NSNumber
movl    L_OBJC_SELECTOR_REFERENCES_-L0$pb(%edi), %ecx    <-- numberWithInt:
movl    %ecx, 4(%esp)
movl    %eax, (%esp)
movl    $42, 8(%esp)   <-- Here's your value
calll   L_objc_msgSend$stub

    // NSNumber *value = @(42);

movl    L_OBJC_CLASSLIST_REFERENCES_$_-L0$pb(%edi), %eax <-- NSNumber
movl    L_OBJC_SELECTOR_REFERENCES_-L0$pb(%edi), %ecx    <-- numberWithInt:
movl    %ecx, 4(%esp)
movl    %eax, (%esp)
movl    $42, 8(%esp)  <--- and here again
calll   L_objc_msgSend$stub

值得注意的是,它甚至足够聪明,可以为您进行预计算:

    // NSNumber *value = @(42 + 1);

movl    L_OBJC_CLASSLIST_REFERENCES_$_-L0$pb(%edi), %eax <-- NSNumber
movl    L_OBJC_SELECTOR_REFERENCES_-L0$pb(%edi), %ecx    <-- numberWithInt:
movl    %ecx, 4(%esp)
movl    %eax, (%esp)
movl    $43, 8(%esp)  <--- Hey; it's precomputed to 43. Nice.
calll   L_objc_msgSend$stub

正如@Zaph 所说,这对编译器无关紧要。

于 2013-11-18T22:17:28.823 回答
2

由于每种情况实际上都将整数“装箱”到一个对象中,因此这是一个清晰的问题,类似于在不需要运算符优先级时添加额外的“()”。
例如:2+3*4 与:2+(3*4)

我个人写@42 不是@(42)
但@(kMeaningOfLifeAndEverything) 没问题;-)

于 2013-11-18T20:09:26.773 回答