Hacker News new | ask | show | jobs
by jarrettc 4089 days 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.

2 comments

Semantically 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.
> 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.

I 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)

Oh, agreed. But how about this:

    let x = BigExpensiveStruct::new();
    some_function(x);
That won't trigger a big, expensive memcpy of the BigExpensiveStruct, will it? I'd thought that its memory was on the heap.
If that's just a struct, it's stack allocated. So it's not ok the heap in the first place. IIRC, LLVM may optimize passing it to the function by reference though.
Good to know. Thanks! So I guess the moral is, if you have a big, expensive struct, make sure the expensive part is in a sub-structure you know is heap allocated, such as a Vec. E.g.:

    struct Expensive {
        cheap_value: u32,
        expensive_value: Vec<u32>
    }
Does that seem like a good maxim?
> Could you elaborate on that?

If the value isn't passed by (perhaps elidably) copying, that would mean it's getting allocated on the heap and deallocated.

Yes, I had understood the struct's memory to be on the heap. My thinking was, keeping the memory on the heap allows for inexpensive moves. Whereas, the pointer to the heap space may indeed be on the stack, as far as I know.

But I could be mistaken. This is all based on hearsay--just stuff I've read about the Rust compiler. I don't actually work on the compiler myself.