繁体   English   中英

目标C类方法与C函数

[英]Objective C Class Methods vs C Functions

在从事开源项目时,我遇到了以下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() ,使用stringFormMimeType()基础仍然需要导入FSNData头文件。

查看Apple文档 ,它仅指出:

因为Objective-C基于ANSI C,所以您可以自由地将直接C代码与Objective-C代码混合在一起。 而且,您的代码可以调用在非Cocoa编程接口中定义的函数,例如/ usr / include中的BSD库接口。

没有提到C函数何时应该支持Objective-C方法。

在这一点上,我看到的唯一好处是,调用上述函数(而不是类方法)将跳过某些Objective-C运行时调用。 FSNData的典型用例中,这不会给用户(甚至可能对开发人员)*带来明显的性能提升。

与类方法相比,使用C函数有什么好处(除了编码风格之外)?

* FSNData用作FSNetworking库的一部分,因此我怀疑在任何应用程序的生命周期中都会执行成千上万的网络操作。

简而言之,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年后悔的事情吧;)

您已经谈到避免objc_msgSend调用的边际性能差异。 Objective-C类方法也要在子类中重写,因此在C中实现方法将防止它在子类中被重写。 相关地,由于运行时继承/多态性,所以无法内联Objective-C方法,而编译器可能内联C函数以提高性能。

谈到避免objc_msgSend ,一个聪明人曾经告诉我:“如果objc_msgSend的开销对objc_msgSend来说太大了,那么Objective-C可能是错误的工作工具。”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM