C/C++与Objective-C数组的比较

4

因此,我正在使用Objective-C制作iPhone应用程序,并需要使用数组。通常在Objective-C中,我会使用NSArray或NSMutableArray,但是我开始怀疑当仅使用基本数组时,这是否是最好的想法。从内存和效率方面来看,当仅保留自定义对象的基本数组时,使用常规C数组还是Objective-C数组更有意义?在Objective-C编程时,您通常使用C数组还是Objective-C数组?谢谢!


当我需要一个整数数组时,我通常会考虑这种方法。将其转换为NSNumber可能很麻烦,且效率低下。 +1 - PengOne
6个回答

6
这实际上取决于您想用数组做什么。对于要进行大量数学计算的数字数组,C数组可能是更好的选择(或者至少是一个封装C数组的类)。如果您不断地在标量和对象之间进行转换,并且没有使用NSArray的更高级功能,那么使用它只会带来很多额外开销。
然而,Cocoa对象具有许多必须遵守的内存管理规则,否则您的应用程序将崩溃。C数组和C++向量会无视这些要求,这意味着您需要更多的工作来使它们保持一致。NSArray将为您处理这些问题。当您处理Cocoa对象时,请使用NSArray。

谢谢,你回答了我的问题。我想在这种情况下我会使用Cocoa类。不过,当对数组进行数学运算时,我明白你的意思,以后我会记住这一点。 - Alexis King

4

除非我找到了不使用它们的充分理由,否则NSArray是我的首选。

在几年的Cocoa编程中,我从未真正找到不使用它的好理由。我唯一能想到的情况是当我想要存储在数组中的内容不是对象时,或者我想存储对象但不希望它们被保留。然而,在这两种情况下,一个简单的CFMutableArrayRef与自定义值回调就可以解决问题。


2

在罗马,就要随俗。

开发iPhone应用程序时,请使用NSArray或NSMutableArray,因为这是惯用的方法。

除非您有非常特殊的原因要使用普通的c数组,否则请遵循惯用的方法。


0

NSArray和NSMutableArray非常高效。如果性能还不是问题,那么没有理由为了使用纯C数组而使自己扭曲,当Objective-C对象更自然时 - 如果以后性能成为问题,那么您可以进行更多的优化。


0

Objective C数组(NSArray等)在处理实时多通道音频和/或实时视频的原始像素位时,效率极低,需要每秒触摸数百万次。以某种数据缓存线感知方式布置的纯C数据数组更为适合,而且在任何重要处理中可能使用的内存和电池功率要少得多。

请注意,您甚至不能将NSArray提供给加速框架,大多数核心音频、核心图形或OpenGL API也是如此。

对于很少接触的数据,例如每秒仅数千次或更少的速率,Objective C数组将有助于内存管理和数据抽象,而且它们的时间和内存惩罚可能很难测量。对于用户数据、UI元素、UI表格和其他以人类节奏进行的真正缓慢的事情非常有用。


我不太同意。我设计并开发了几个备受关注的视频会议工具,并围绕 ObjC 集合构建了实时视频和音频流处理链。主要好处是消除了为了线程安全而从缓冲区复制数据到缓冲区的需要,而是大量使用 ObjC 的对象所有权模型(保留计数)。我发现 NSArray、NSDictionary、NSSet 和 NSData(更不用说它们的 CF“基础”类)高度优化,当按照 Cocoa 的设计思路使用时,比以前使用的实现方法要优秀得多。 - Motti Shneor
在视频帧速率下,你可能没问题。但是在几年前的WWDC上,苹果明确建议不要在音频实时环境中使用Objective C或Swift属性或线程安全锁。我还没有看到任何官方撤回这个建议的消息(还没有吗?)。我使用无锁环形缓冲区在线程之间传递流数据(实时软件定义无线电应用程序)。 - hotpaw2
他们当时的意思是不要愚蠢到为每个音频“帧”(几个音频样本)分配一个Obj-C对象(或CF对象)。有数百万个它们在运行...但如果您使用包含音频数据的NSData对象的NSArray批量处理音频数据(通常从系统的低级部分接收),那么您就可以放心使用。我永远不会在紧密循环中创建Obj-C对象-谁知道ARC或其他内存管理在压力和何时下执行如何?但作为集合-特别是高级语义的集合-我发现它们非常好用。 - Motti Shneor
环形缓冲区很好用,但是每次复制数据进入和从中读取都要付出高昂的代价。如果你收到新数据时,只需将其包装在NSData对象中,并将其添加到一个集合中(比如NSArray),以完全替换环形缓冲区,那会怎样呢?根本不需要复制任何数据!这被证明非常高效。经典的音频/视频引擎一直在不断地从层到层复制数据,而使用Cocoa集合类可以避免这种情况。 - Motti Shneor
包装NSData或修改集合需要内存管理。苹果公司明确建议不要在音频实时上下文中执行任何可能涉及内存管理的Obj C代码(请参阅WWDC 2017会话501)。 - hotpaw2
Obj-C的内存管理仅仅是保留-释放,当你明智地行事时,你可以在现有的内存缓冲区周围创建NSData对象(甚至是从驱动程序接收到的'malloc'ed),从而避免真正的“内存管理”。此外,我指出足够大的数据块(例如大多数系统传递的压缩音频普通缓冲区)即使在实时链中也能很好地工作。唯一重要的事情是不要在实时紧密循环中分配/释放Obj-C对象。就这些。 - Motti Shneor

0
虽然我基本上同意首选答案,但是我认为它缺乏根本的标准,即:当为iPhone编程时,您编写的代码仅代表应用程序总体完成量(在CPU周期内存等方面)的少数百分比。其余部分由Cocoa-Touch框架和操作系统完成。通常,您的数据结构(包括数组)只会在使用Cocoa API调用时起到中间作用。然而,这些API仅接受NSArrays、NSDictionaries等。因此,如果选择使用C数组,则必须很快重新构建NSArrays(例如,在UI中显示数据、查询数据库或发送网络请求),这种来回切换成本很高。
此外,Foundation集合类(如NSArray)经过高度优化,并自动适应不同的场景(例如,NSArray可以在其实现中使用C数组,并将它们转换为树结构,如果数组很大,甚至可以作为链接列表,如果只有少数索引被填充)。从长远来看,您将发现它们比C数组更具优越性,因为您不需要每次需求变化时重新架构应用程序。苹果正在为您做这件事。
对于简单的需求和相对较小的数组,性能差异(如果有的话)可以忽略不计。

这并不意味着在iPhone开发中没有使用C数组的地方 - 只是它们(可以理解的)使用很少。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接