4 ms·
The author mentions that Rust's "Box type is an owning type" and compares Box to C++'s std::unique_ptr. Worth noting: Rust's most basic variable syntax provides
by jarrettc 11y ago
The author mentions that Rust's "Box type is an owning type" and compares Box to C++'s std::unique_ptr. Worth noting: Rust's most basic variable syntax provides unique_ptr-like behavior, so you usually don't need the Box type for this behavior. For example:
https://gist.github.com/jarrett/fe3f24c301a586efd7c1 https://gist.github.com/jarrett/fe3f24c301a586efd7c1
- SamReidHughes 11y agoAre you sure your comments are right? It seems to me like the value would be memcpyed, when you pass by value. There is not one unit of memory that is "taken over," or if there was, then Rust would have a serious problem.
- masklinn 11y agoHis comment is right in that all of Rust's values do have move semantics by default (checked by the compiler), that's not specific to Box<T>.
- SamReidHughes 11y agoI said comments.
- cpeterso 11y agoThe Rust documentation on ownership shows examples of function with reference parameters and Box parameters, but nothing like the OP's `fn take_ownership(obj: MyStruct)` example. Is that an oversight in this page in Rust docs? http://doc.rust-lang.org/nightly/book/ownership.html http://doc.rust-lang.org/nightly/book/ownership.html
- masklinn 11y ago> nothing like the OP's `fn take_ownership(obj: MyStruct)` example. It uses Box to demonstrate ownership in the first section, but that works the same way with any Rust type unless said type was opted into copy semantics, there's nothing special or magical about Box (at least in that respect), it's just a wrapper for a raw pointer.
- dbaupp 11y agoI think it is an oversight: Box isn't particularly special with how it handles ownership, but people do get the wrong impression that Box is the way to have uniquely owned data, whereas it is actually the default. This happens less now that Box doesn't have special syntax, but I agree with you that we may be able to improve those docs in this respect. Unfortunately, it can be hard to have an example that's simple enough to understand, while still emphasising the right concepts. Hopefully we can find something.
- phaylon 11y agoIt might be a terminology thing. Assuming MyStruct only contains values, it will fully live on my_func's stack and nothing needs deallocating on drop. When take_ownership is called a copy of it's value would be passed in, and the original location marked unusable (assuming MyStruct doesn't implement Copy). So yeah, there's isn't any specific memory location being taken over, since there's two locations involved.
- jarrettc 11y ago> It seems to me like the value would be memcpyed, when you pass by value. As far as I know, the compiler should not copy in that instance. Rather, it should move. > There is not one unit of memory that is "taken over," or if there was, then Rust would have a serious problem. Could you elaborate on that? Rust does have an ownership model, and ownership can be transferred as in the example. What sort of problems would you expect that to cause? If you're worried that it will invalidate existing pointers, the compiler checks that for you. Unless you deliberately circumvent the check, the compiler guarantees that your pointers are valid.
- steveklabnik 11y agoSemantically speaking, the only difference between a move and a copy is that you're allowed to use a copy type afterwards, and you're not allowed to use a move type afterwards. It's still a memcpy. Of course, these may be elided by optimization passes.
- jarrettc 11y ago> Semantically speaking, the only difference between a move and a copy is that you're allowed to use a copy type afterwards Are you speaking about Rust specifically, or move in general? I had always understood that move was no more expensive than passing by reference. That is, I had thought the memory was on the heap and didn't need to be copied each time someone new took ownership of that heap space.
- steveklabnik 11y agoI mean in Rust. > That is, I had thought the memory was on the heap An example: let x = Box::new(5); let y = x; While the 5 is allocated on the heap, when we move x to y, _the pointer itself_ is memcpy'd. That's why Box<T> isn't Copy; as you say, a simple memcpy won't actually duplicate the structure. Make sense? (and in this case, I'd assume llvm's optimizations would realize the copy is superflous and just elide it, but semantically, that's what's up)
- cwzwarich 11y agoThe default mode in Rust is value semantics, similar to C++'s default. Rust does have the advantage of move-by-default on uses and checking the validity of moves, but if you want unique_ptr behavior then you need Box. C++ has the advantage (if you would call it that) of allowing arbitrary code in move constructors.
- phaylon 11y agoI think he was more talking about the unique ownership part, especially that values themselves follow the same rules. Which I find fitting, since in Rust, the Box is (at least to me) more about indirection. The single-owner semantics just come in because Box follows the same rules as anything else, while for unique_ptr they are part of the pointer concept.