在从事开源项目时,我遇到了以下 C 函数声明和实现:
// FSNData.h
NSString *stringForMimeType(MimeType type);
@interface FSNData : NSObject
// All the expected objective-c property and instance method declarations
@end
// FSNData.m
#import "FSNData.h"
// where 'type' is an enum
// this does work as expected
NSString *stringForMimeType(MimeType type) {
switch (type) {
case MimeType_image_jpeg: return @"image/jpeg";
case MimeType_image_png: return @"image/png";
default:
NSLog(@"ERROR: FSNData: unknown MimeType: %d", type);
// do not return "application/octet-stream"; instead, let the recipient guess
// http://en.wikipedia.org/wiki/Internet_media_type
return nil;
}
}
@implementation
// all properties and methods defined in FSData.h implemented as expected
@end
这个例子可以很容易地重写为类级别的方法,没有任何问题。事实上,使用stringFormMimeType()
sill 需要导入FSNData
无论如何,头文件。
看着苹果文档,它仅指出:
因为 Objective-C 建立在 ANSI C 的基础上,所以你可以自由地
将直接 C 代码与 Objective-C 代码混合在一起。此外,你的代码
可以调用非 Cocoa 编程接口中定义的函数,例如
作为 /usr/include 中的 BSD 库接口。
没有提到 C 函数何时应该支持 Objective-C 方法。
此时我能看到的唯一好处是,与类方法相反,调用上述函数会跳过一些 Objective-C 运行时调用。在一个典型的用例中FSNData
,这不会给用户(甚至可能是开发人员)带来性能的显着提升*。
与类方法相比,C 函数有什么好处(除了编码风格)?
*FSNData
被用作FS网络库,所以我怀疑在任何应用程序的生命周期中都会执行成千上万的网络操作。
简而言之,C(或 C++)实现非常有用:
- 对于抽象
- 为了可重复使用
- 制作中大型节目时
- 在性能关键路径中
- 对于“内部”实施
与类方法相比,C 函数有什么好处(除了编码风格)?
- ObjC 消息传递引入了间接函数调用。这些是优化器的防火墙。
- C 函数可以轻松限制访问,而“私有”ObjC 实现可能会使用 ObjC 运行时查找或意外覆盖。
- 如果未引用,C 函数可能会从可执行文件中删除,或者可能会被设为私有。如果您编写可重用的代码(并且您应该),这可能会对您的二进制大小和加载时间产生巨大影响 - 未引用/使用的 C 函数可能会被删除,但 ObjC 类型和方法将被保留(包括它们的所有内容)参考)。这就是为什么当您仅使用 ObjC 静态库的一小部分时,您的应用程序的二进制大小可能会显着增加 - 库中的每个 objc 类都会被保留。如果该库是 C 或 C++,那么您只需很小的增长即可完成,因为您只需要引用的内容。使用 C 和 C++ 更容易证明引用或未引用的内容。
- C 函数可以在编译期间或链接时间优化阶段内联。
- 编译器和优化器能够对 C 函数进行很多优化(例如过程间优化),但对 ObjC 方法却很少,因为它们总是间接的。
- 避免 ObjC 消息调度开销(正如您提到的)
- 与 ObjC 对象交互时,可能会进行额外的引用计数操作和自动释放池活动。
当然,您不会总是为不需要或不需要的东西付费——并且记住 ObjC 类方法也比 C 函数有一些好处。因此,只需将 C 或 C++ 实现视为工具箱中的另一个工具即可。我发现随着复杂性和项目规模的增加它们非常有用,并且它们可以用来使您的程序更快。 2015 年就做你最不会后悔的事吧;)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)