为啥 Objective-C 对象必须动态分配?

Posted

技术标签:

【中文标题】为啥 Objective-C 对象必须动态分配?【英文标题】:Why do Objective-C objects have to be dynamically allocated?为什么 Objective-C 对象必须动态分配? 【发布时间】:2011-08-16 04:50:56 【问题描述】:

为什么 Objective-c 对象必须动态分配?为什么我必须让它成为一个指向对象的指针,不像在 C++ 中我可以在堆栈上创建它们? 谢谢。

【问题讨论】:

因为 Bjarne Stroustrup 选择实现复制/按值语义,而 Brad Cox/NeXTSTEP/Apple 选择不实现。 【参考方案1】:

主要原因:不知道要保留多少堆栈大小。

现有的约定和用途也使得解除限制相当困难。

在这种情况下,动态消息传递无关紧要,因为在初始化时设置正确的“vtable”很简单。

在 c++ 中,堆栈对象的大小始终是已知的(如果它是错误的,你知道会发生什么)。一个 objc alloc/init 序列可以返回多种类型中的任何一种——每种都有不同的大小(它本质上是一个工厂),或者什么都没有。

大小也可以在运行时变化(例如,您可以通过运行时向类添加字段)。

更新 1

我对此很好奇,所以我做了一个小测试程序作为概念验证。

我能够实现一个简单的基于堆栈的 objc 类层次结构,它还实现了NSObject 的大部分接口——当然,省略了引用计数和动态分配接口,因为它与证明无关的概念。无论如何,我的简单类层次结构与 NSObject 类或协议完全兼容,因此出于显而易见的原因,它不应该用于预期 NSObject 类型的地方。因此,如果您真的想要基于堆栈的 objc 对象,可能的(并且不是特别困难)。

您不必执行与 c++ 不同的任何操作来保留堆栈空间。在某些领域(考虑工厂方法、类集群等),要保留的堆栈大小仍然是一个限制。

还有一些运行时功能在默认情况下不起作用。这里最好的例子是在运行时添加 ivars 的能力。如果需要,您实际上可以容纳此功能。我没有打扰那个练习。

自然地,基本接口可能有几个偏差 - 我为了好玩而做出的一个偏差是添加了交换活对象的实现(类型)的能力。

玩得开心

更新 2

事实证明,GCC 接受了我编写的概念证明。不幸的是,由于在保留正确大小时可能遇到的问题/危险(考虑到语言的动态特征......),这已在 clang 中被禁止。例如:clang 禁止sizeof(NSObject)。哦,好吧。

【讨论】:

堆栈对象的一个​​缺点是没有所有权的概念——它们必须在块/函数/堆栈范围的末尾被销毁。这意味着堆栈范围之外的任何东西都需要复制堆栈对象。 我更喜欢将其称为另一种(自动)所有权模型。所有权都是明确定义的,它与动态模型不同。在我编写的 c++ 程序中,最常使用本地创建的自动对象(而不是通过分配器进行分配),这非常重要。当两种模型都可用并且一个需要返回分配的对象时,在大多数情况下,您提到的临时对象可能会在您知道需要它时通过创建动态对象来绕过:return new MON::t_string(number);。无论好坏,c++ 都只有 more 另一个问题:Objective-C 最初是作为生成 C 代码的预编译器实现的。在这种情况下,如果参数的类型与参数类型不同,则按值传递对象是一个问题。可以转换指针,而转换 structs 则不是,即使它们具有相同的初始布局。 如果您还没有阅读:Friday Q&A 2010-01-15: Stack and Heap Objects in Objective-C. 我能够使用 class_getInstanceSize()、alloca() 和 object_setClass() 在堆栈上创建对象。这也应该使动态大小正确。类集群仍然是一个问题。 gist.github.com/iamleeg/5290797【参考方案2】:

Objective-c 是一种动态语言,这意味着它的一切都可以在运行时改变。对象的类对象仅在从可执行文件加载时创建,并且可以按类别更改。此外,运行时可以实例化属性的变量。由于对象在编译后会发生很多变化,因此在使用之前无法创建。

【讨论】:

【参考方案3】:

这是因为 Objective-C 使用动态或后期绑定的方式。与 C++ 不同,在 C++ 中,您总是可以选择通过对象调用类的函数,还是通过同一类甚至超类的指针。在后一种情况下,需要多态性。

然而,在 Objective-C 中总是存在在运行时确定正确函数的能力。不同之处在于,例如在 C++ 中,编译器必须确保使用的函数存在,而在 Objective-C 中,编译器并不真正关心,运行时系统只决定。

【讨论】:

以上是关于为啥 Objective-C 对象必须动态分配?的主要内容,如果未能解决你的问题,请参考以下文章

为啥必须动态分配扩展数组才能使此函数正常工作 C++

在 Objective-C 中,为啥在分配给指定类型的变量时需要强制转换?

为啥我们不能在堆栈上分配动态内存?

为啥在单个语句中分配动态对象的成员变量会导致 PHP 中的语法错误?

Objective-C 对象的分配/释放

为 Objective-C 数据对象分配内存的问题