ios Swift 通过引用传递结构?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31495431/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swift pass struct by reference?
提问by Esqarrouth
I've looked to similar questions but I haven't seen an answer that I am satisfied with.
我看过类似的问题,但没有看到令我满意的答案。
Is it possible or advisable to pass structs by reference? If so how?
是否可以或建议通过引用传递结构?如果是这样怎么办?
Here is a code as a reference for examples:
这是一个代码作为示例的参考:
struct MyData {
var contentId: Int = 0
var authorId: Int = 0
var image: UIImage = UIImage(named: "myimage")
}
As you see my main reason of doing this is because not having my image multiplying all over the place.
正如你所看到的,我这样做的主要原因是因为我的形象没有到处成倍增加。
回答by Rikki Gibson
Structs can be passed by reference using the inout
keyword and the &
operator.
可以使用inout
关键字和&
运算符通过引用传递结构。
struct Test {
var val1:Int
let val2:String
init(v1: Int, v2: String) {
val1 = v1
val2 = v2
}
}
var myTest = Test(v1: 42, v2: "fred")
func change(test: inout Test) {
// you can mutate "var" members of the struct
test.val1 = 24
// or replace the struct entirely
test = Test(v1: 10, v2: "joe")
}
change(test: &myTest)
myTest // shows val1=10, val2=joe in the playground
This practice is discouraged unless you can prove it's the only way to get the performance you need in a critical situation.
不鼓励这种做法,除非您能证明这是在危急情况下获得所需性能的唯一方法。
Note that you won't save the burden of copying the UIImage by doing this. When you put a reference type as a member of a struct, you still only copy the reference when you pass it by value. You are not copying the contents of the image.
请注意,这样做不会减轻复制 UIImage 的负担。当您将引用类型作为结构的成员时,您仍然只在按值传递引用时复制引用。您不是在复制图像的内容。
Another important thing to know about struct performance is copy-on-write. Many built in types like Array are value types, and yet they're very performant. When you pass around a struct in Swift, you don't undergo the burden of copying it until you mutate it.
关于 struct 性能的另一个重要信息是copy-on-write。许多内置类型(如 Array)都是值类型,但它们的性能非常好。当你在 Swift 中传递一个结构体时,你不会承担复制它的负担,直到你改变它。
Check out the WWDC video on value typesto learn more.
回答by Qbyte
First of all, if you pass a struct it gets normally passed by value. Even though all properties of the struct get copied only the pointer to properties which are reference types like UIImage gets duplicated (only 8 bytes):
首先,如果你传递一个结构体,它通常是按值传递的。即使结构的所有属性都被复制,只有指向像 UIImage 这样的引用类型的属性的指针被复制(只有 8 个字节):
var data1 = MyData()
var data2 = data1
// both data1 and data2 point to the same image
Also the compiler optimizes the code so structs get internally passed by reference and copied if needed.
编译器还优化了代码,以便在内部通过引用传递结构并在需要时进行复制。
As an example of passing a struct by reference in top level code you can use inout
parameters:
So an inout
parameter can be passed by reference but Swift's general way of implementing inout
is that the parameter gets passes by value and after the function returns it gets reassigned.
作为在顶级代码中通过引用传递结构的示例,您可以使用inout
参数:因此inout
参数可以通过引用传递,但 Swift 的一般实现方式inout
是参数通过值传递,并在函数返回后重新分配。
Although the compiler optimizes the function call so you could get a true reference in some situations. This optimization only affects variables which aren't computed or have a property observer like willSet
and didSet
(and probably other cases).
尽管编译器优化了函数调用,因此在某些情况下您可以获得真正的引用。此优化仅影响未计算或具有属性观察器(如willSet
和)didSet
(可能还有其他情况)的变量。
So you should only rely on the current instance which is not in the scope of the function:
所以你应该只依赖不在函数范围内的当前实例:
struct Test {
var value = 0
}
// case 1
var myTest = Test()
// case 2
var myTest = Test() {
didSet { print("I was set") }
}
// case 3
var myTest: Test {
get{ return Test() }
set{ print("I set myself") }
}
func mutateTest(inout t: Test) {
// directly referencing to myTest
myTest.value // value = 0 in all cases
t.value = 42
myTest.value // value = 42 in case 1 ; value = 0 in case 2 and 3
t = Test() // nothing gets printed
myTest.value // value = 0 in all cases
t = Test() // nothing gets printed
t.value = 3 // value = 3 in case 1 ; value = 0 in case 2 and 3
}
changeTest(&myTest)
//case 2: "I was set", case 3 "I set myself" get printed now
myTest.value // value = 3 in all cases
As you can see myTest
and t
are only equivalent in case 1 ("true" reference semantics). So this makes a huge difference if you also reference myTest
in the function itself. But as long as you don't do this you are good to go.
如您所见myTest
,t
并且仅在情况 1(“真实”引用语义)中等效。因此,如果您还引用myTest
了函数本身,这将产生巨大的差异。但只要你不这样做,你就可以继续。