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 参数用法
In-Out Parameters inout keyword