Objective-C in,out,inout,byref,byval, .. 等等。这些是啥?

Posted

技术标签:

【中文标题】Objective-C in,out,inout,byref,byval, .. 等等。这些是啥?【英文标题】:Objective-C in,out,inout,byref,byval, .. and so on. What are they?Objective-C in,out,inout,byref,byval, .. 等等。这些是什么? 【发布时间】:2011-04-10 03:23:37 【问题描述】:

我在阅读 @encoding 的 Objective-C 手册时发现了一些不熟悉的东西。

Table 6-2  Objective-C method encodings
Code Meaning
r    const
n    in
N    inout
o    out
O    bycopy
R    byref
V    oneway

我只知道oneway。其他的呢?

【问题讨论】:

【参考方案1】:

这些是分布式对象使用的方法参数和返回值的注释。我说 是因为在 Apple 的文档中显然已经没有它们的迹象了。 Objective-C 编程语言文档中曾经有一个远程消息传递部分,分布式对象编程主题文档仍然引用该部分。

in: 参数只是一个输入参数,以后不会被引用 out: 参数只是一个输出参数,用于通过引用返回一个值 inout: 参数既是输入参数又是输出参数 const:(指针)参数是常量 bycopy:不使用代理/NSDistantObject,而是传递或返回对象的副本 byref:使用代理对象(默认)

【讨论】:

非常感谢!特别是,文档不再可用。事实上,我一直在寻找文档,但所有链接都已损坏。 FWIW,Apple 在新的 UIScrollViewDelegate 方法中使用了 inout。 (targetContentOffset:(inout CGPoint *)targetContentOffset。反正我就是这样过来的。 其实我也是。如果他们可以使用 inout,为什么他们需要做一些复杂的事情,比如做双指针来获取错误?实际上,考虑到他们通过了 CGPOINT *,他们根本不需要指定 inout。这是一个指针。 CGPOINT 是一个结构。只要把新的CGPOINT放到targetContentOffset指向的地址上就行了。 更多参考 NSDateFormatter.h apple 使用 inout,out 作为键的验证值。 -(BOOL)validateValue:(inout __autoreleasing id *)ioValue forKey:(NSString *)inKey 错误:(out NSError *__autoreleasing *)outError【参考方案2】:

除了分布式对象之外,ARC 似乎还使用了这些注释之一。我在clang对passing to an out parameter by writeback的描述中遇到了以下内容:

如果参数不是标记为out的Objective-C方法参数,则读取*p,并将结果写入具有原始语义的临时对象。

这与- (BOOL)executeWithError:(out NSError **)error 之类的方法有关。

忽略out 关键字,ARC 有一个well-defined behavior of treating by-reference object passing as __autoreleasing,因此ARC 将error 参数视为具有NSError * __autoreleasing * 的类型。如果您使用其他限定的变量,ARC 将添加一个临时自动释放变量传递到函数中(为了连贯性):

原始代码

NSError *error;
[obj executeWithError:&error];

伪转换代码

NSError * __strong error;
NSError * __autoreleasing temp;
temp = error;
[obj executeWithError:&temp];
error = temp;

使用上面的代码,如果我们能以某种方式知道temp 永远不会被读取,那么temp = error 行将是不必要的。这就是out 注释发挥作用的地方。根据引用的描述,如果缺少out,编译器必须添加行temp = error,但如果它确实包含out,它可以排除该行并使代码更小/更快。使用out,转换后的代码变为:

NSError * __strong error;
NSError * __autoreleasing temp;
[obj executeWithError:&temp];
error = temp;

当然,如果您担心二进制文件的大小和速度,您只需编写以下代码:

NSError * __autoreleasing error;
[obj executeWithError:&error];

这些注解完全有可能在整个编译器和运行时的其他地方使用,并且将来可能会在更多地方使用。就个人而言,我喜欢使用out 来暗示其他开发人员我不会阅读该值。

【讨论】:

Original Code 似乎缺少一个地址运算符。 executeWithError:&error]; 感谢@Eonil,已修复! @BrianNickel 所以 (out NSError **) 和 (NSError * __autoreleasing *) 是一样的吗? @denis631 No. (out NSError **)(out NSError * __autoreleasing *) 相同,(NSError **)(NSError * __autoreleasing *) 相同类型。 __autoreleasing 的注入是 ARC 设计的一部分,类似于所有变量都是 __strong,除非另有说明。 out 不是类型的一部分,而是编译器可以用来优化的注解。 @BrianNickel 那么“out”关键字有什么作用?它只删除了这行代码: temp = error;还是做更多的事情?【参考方案3】:

如果有人偶然发现这篇文章并且和我有同样的困惑,'in' 参数也可以是代表快速枚举的关键字。详情请见here。

【讨论】:

这种常见的结构在其他当前语言中,如 Java 和 Python,但实际上从未在 Obj-C 中使用过。就个人而言,当我需要这种东西时,我倾向于使用 blockEnumerators,即使它涉及更多的输入...... IDK,我觉得任何阅读我的代码的人更有可能立即得到它。【参考方案4】:

您可以阅读 Objective-C 运行时源代码http://www.opensource.apple.com/source/objc4/objc4-437.1/ 以了解这些注释的含义。

【讨论】:

以上是关于Objective-C in,out,inout,byref,byval, .. 等等。这些是啥?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 存储过程传参之in, out, inout 参数用法

AIDL中的in,out,inout

In-Out Parameters inout keyword

Mysql储存过程6: in / out / inout

mysql存储过程的-创建(in,out,inout)-删除-查看

mysql存储过程中的 in , out , inout