> On Nov 4, 2016, at 5:59 AM, Ryan Lovelett via swift-users > <swift-users@swift.org> wrote: > > struct Foo { > init(from buffer: Data) { > bar = integer(withBytes: Array(buffer[4..<6])) > baz = integer(withBytes: Array(buffer[6..<8])) > ... > } > > let d = Data(count: Int(3e+8)) > let f = Foo(from: d) > > Did I just make two copies of the `Data`? How would I investigate this > to understand it?
Do you mean, "did I make two copies of the `Data`, one in a top-level variable named `d` and the other in a parameter named `buffer`"? If so, then answer is "Yes, but…" A value type like `Data` can't really hold variable-sized data like the bytes in a `Data` object. Instead, the bytes are stored in a separate object, and `Data` manages that with copy-on-write semantics. In other words, there are two copies of the `Data` instance itself, but they share a single copy of the bytes they're storing. To illustrate more clearly, after this line: let d = Data(count: Int(3e+8)) You have something like this: | ...stack frame for top level... | +-------------------------------+ | Data instance (d) | --------------> | ...3e+8 bytes of data... | | | +-------------------------------+ And then once you execute the call on this line: let f = Foo(from: d) You have this: | ...stack frame for top level... | +-------------------------------+ | Data instance (d) | --------------> | ...3e+8 bytes of data... | | | +-------------------------------+ | ...stack frame for Foo(from:) | ^ | Data instance (buffer) | ---------------------------------+ If `Foo(from:)` were to copy `buffer` and then mutate the copy, the bytes would be copied before the mutation occurred. But since neither `f` nor `buffer` is mutated in this code (indeed, both are in immutable variables!), that never happens here. > I _think_ that if I made it `inout` then it would not make a copy but > now the data buffer is mutable. I want it to be clear I'm not mutating > the buffer inside the initializer but I also want to be sure I'm not > making a copy of the buffer either. That's implementation-specific. Notionally, an `inout` variable is essentially passed in by value, modified as a copy, returned to the caller, and then assigned back to the original value. In some cases that's basically what actually ends up happening. But Swift tries to optimize `inout` behavior into directly mutating the original variable, and it's often successful. -- Brent Royal-Gordon Architechies _______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users