【问题标题】:Are objects in Objective-C ever created on the stack?Objective-C 中的对象是否曾经在堆栈上创建过?
【发布时间】:2014-01-06 22:34:47
【问题描述】:

据我了解,在 C++ 中,您可以在堆栈上创建对象:

SomeClass object = SomeClass();

或在堆上:

SomeClass *object = new SomeClass();

在 Objective-C 中,您似乎总是在堆上创建对象,因为 [SomeClass alloc] 返回一个指向新实例的指针。这是正确的吗?

是否曾经在堆栈上分配过对象?如果是这样,什么是一个很好的例子?否则,为什么不呢?

【问题讨论】:

  • int x=0; ?(目标 C)

标签: objective-c memory-management heap-memory alloc


【解决方案1】:

将在堆栈上创建基本的原始类型(int、float 和 double)。

实际的指针(即SomeClass* object中的object)是在堆栈上创建的,即使它指向堆上的一个对象。

你说的没错,用new 创建的任何东西都是在堆上创建的。

【讨论】:

  • 我知道原语和指针。但是实际的对象永远不会放在堆栈上,即即使你想也做不到?
  • 不,不是所有对象都是用new创建的。
  • “所有对象都是用new 创建的”是什么意思?在 Objective-C 中?你不是说alloc吗?据了解,Objective-C 中的new 只是alloc/init 的一个快捷方式。
【解决方案2】:

简短的回答是对象总是在堆上分配,而不是在栈上。

不过,这还不是全部。在 Objective-C 中,块也是完整的 Objective-C 对象。它们的特殊之处在于它们有时在堆栈中。特别是,使用块字面量语法创建的块以及引用周围范围的块都在堆栈上。如果您检查他们的课程,您甚至可以看到这一点,这将是(私人)NSStackBlock。如果您使用Block_copy() 或-copy 复制它们,则生成的副本将在堆上(NSMallocBlock)。

这意味着堆栈分配的块仅在创建它们的范围结束之前有效。在 ARC 之前(以及早期版本的 ARC 中的 IIRC),这意味着您必须复制您想要超过其创建范围的块,以便它们在堆上。 ARC 现在在大多数情况下都会为您处理这个问题,这也意味着更难预测一个块是在堆栈上还是在堆上。

这个小测试程序显示了这个(使用 ARC 编译关闭):

#import <Foundation/Foundation.h>

// Compile this without ARC.

int main(int argc, char *argv[]) {
    @autoreleasepool {

        NSMutableString *string = [NSMutableString stringWithString:@"foo"];
        void(^stackBlock)() = ^{
            [string setString:@"bar"];
        };
        NSLog(@"stackBlock class: %@", NSStringFromClass([stackBlock class]));

        void(^heapBlock)() = [[stackBlock copy] autorelease];
        NSLog(@"heapBlock class: %@", NSStringFromClass([heapBlock class]));
    }
}

输出:

stackBlock class: __NSStackBlock__
heapBlock class: __NSMallocBlock__

(为了清楚起见,您当然不应该在实际代码中检查NSStackBlock/NSMallocBlock。它们是私有实现细节类。此代码仅用于演示。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 2012-01-23
    • 2021-01-17
    • 2014-10-23
    • 2020-03-30
    相关资源
    最近更新 更多