ARC下的结构体中的Objective-C类

11

我尝试创建一个包含类的结构体,代码如下:

struct my_struct
{
    NSString *string;
    // more fields
};

令人惊讶的是,在启用ARC的情况下,Objective-C++ 允许这样做。
它可以在每个赋值中轻松保留字符串,但释放是个问题。
它可以添加一个带有释放功能的析构函数,但这将使结构体变得非平凡。
它也可以使这个不保留或释放,但要这样做就需要使用unsafe_unretained。

根据我的观察,使用这种方法时不会出现任何崩溃,但我想知道这里实际发生了什么。


仅供猜测,但是根据我的经验,由于需要包括unsafe_unretained,它可能会默认为unsafe_unretained - Patrick Perini
@pcperini:那么在自动释放池被弹出之后应该会崩溃,但它没有。你是在Objective-C还是Objective-C++方面有经验?在C中无法添加析构函数。 - Daniel
Objective-C :) - Patrick Perini
1个回答

9
请参见ARC文档中的4.3.5:http://clang.llvm.org/docs/AutomaticReferenceCounting.html#ownership.restrictions.records
不允许声明C结构体或联合体的成员具有非平凡所有权限定类型,否则程序会被认为是不规范的。这是因为所得到的类型在C++意义上不是POD,但是C语言并没有为我们提供很好的语言工具来管理聚合体的生存期,因此禁止使用它们更加方便。可以使用void*或__unsafe_unretained对象来管理它们。
在Objective-C++中不适用此限制。但是,在C++11中,非平凡所有权限定类型被认为是非POD:它们不能进行平凡的默认构造、拷贝构造、移动构造、拷贝赋值、移动赋值或析构。在ARC下,如果使用一个类,该类在ARC下具有非平凡所有权限定成员,则违反了C++的单一定义规则。
建议不要在ObjC++中使用它。强烈建议不要广泛使用ObjC++。它是一个桥接语言,用于帮助纯ObjC和纯C++相互通信。它有很多问题。将ObjC++与ARC结合使用会引入时间和空间性能成本,这在ObjC中不会发生,以使其具有异常安全性。定义这些类型的ObjC++特定数据结构使得与非ObjC++代码和非ARC代码交互变得困难(请注意,不能在ARC之外使用此代码)。大部分应该从ARC中免费获得的东西突然变得困难,因为你必须再次担心内存管理(正如你已经发现的那样)。
建议建立一个纯ObjC层、一个纯C++层和一个薄的ObjC++层来将两者联系起来。不要将ObjC对象放在结构体中,绝对不要放在任何公共结构体中(即在定义它的单个ObjC++对象之外可见)。

3
Rob说得没错!我想补充一点,你也可以关闭ARC,手动管理内存来创建一个可维护的粘合层,因为这样做可以提供精确和明确的控制,特别是对于非常薄的ObjC++层。 - bbum
所以,归根结底,它是安全的,但它使结构变得不太简单? - Daniel
2
几乎任何时候,在两种编程语言之间进行桥接(即使是在 Objective-C 和基于纯 C 的 CF 之间,尽管它更简单),都会因边界处的阻抗失配而出现脆弱性和复杂性。这正是为什么希望保持边界尽可能小并完全隔离的原因;为每个 C++ 类创建一个简单的 Objective-C 包装器或类似物。 - bbum

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