我正在比较不同的编程语言和开发平台。 objective-c 和其他语言的一个重要区别是它使用选择器、消息,所以每次都调用 objc_msgSend,跨越共享库的边界,因此引入了可测量的开销,加上 objc_msgSend 的进一步开销(在缓存的情况下很少)内部运作,就像这里解释的那样: http://www.mulle-kybernetik.com/artikel/Optimization/opti-3.html 我不是专家,所以我必须相信在这个论坛上找到的这篇文章。 在 Apple 官方指南中,我发现“点语法”只是“语法糖”,即使用相同的方法调用机制。 问题:我想知道纯调用是否在类实例内部执行,调用 objc_msgSend 是一种浪费。那是当一个类实例的方法被同一个类实例的方法调用时。 谢谢
最佳答案
以假设的 OOP 语言考虑这种情况:
class A {
say_something(){
print("A!")
}
do_something(){
say_something()
}
}
和
class B : extends A {
say_something(){
print("B!")
}
}
现在假设你有一个 B
的实例,并调用 do_something
:
B b;
b.do_something();
b
应该打印A
还是B
?如果在 do_something
的实现中对 say_something
的调用通过 vtable
(在 C++ 中)或 obj_msgSend
(在Obj-C),它会打印B
,但是如果编译器决定调用同一个类中的方法应该调用同一个类中的方法,它会打印A
。
哪个是可取的取决于情况。因此,在 C++ 中,您可以选择是否将成员函数标记为 virtual
。
在 Objective-C 中,每个方法都是虚拟的。
因此,即使在 C++ 中,您建议的优化也不会针对虚方法进行。我不会说没有虚拟方法的语言是适当的 OOP 语言。
无论如何,现在您可能会担心它会降低 Obj-C 应用程序的性能。 Apple 知道其中的危险,因此他们进行了大量优化。例如,在最近的运行时中,objc_msgSend
位于固定地址,因此您无需先通过共享库边界。
Mulle-Kybernetic 文章也不错,但也请注意它非常过时:它是十年前的,在这个行业中是史前时代。您可以在 bbum's blog posts 中阅读有关 objc_msgSend
实现的最新优化。或 Hamster's blog posts .
如果您正在编写管理 UI 的代码,使用标准消息传递(即幕后的 objc_msgSend
)就足够了。它甚至可以在移动设备上运行得非常流畅!因此,不要通过获取 IMP
等进行过早的优化,直到在测量代码的性能后证明这是绝对必要的。
如果您正在编写计算密集型代码,例如涉及数以万计的粒子移动,是的,我建议不要使用 Obj-C 消息传递框架。在那种情况下,只需简单地编写一个 C 代码(它总是可以在 Objective-C 中使用)或 C++ 代码(它可以在 Objective-C++ 中使用。)
关于objective-c:类内部的方法调用是否仍然使用选择器或纯调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6717843/