I've started to try to understand more what move semantics is and how and when 
I can make my code benefit from it. I've watched Araq's talk on it and read a 
few threads on the forum along with the Destructors page in the docs. But I 
don't feel like I've really managed to nail down what's the difference between 
a copy and a move. So I have a few cases that I wanted to ask about regarding 
objects and seqs. Correct me if I'm saying something wrong in my assumptions 
here :-)

**Case 1:** Say we have a purely stack-allocated object: 
    
    
    type
      MyObj = object
        # only int, floats or other stack-allocated objects here
    
    proc consume(x: sink MyObj) =
      # Do something with it
      discard
    
    proc ex1() =
      var x = MyObj()
      var y = x # a move, right? Because x isn't used anymore
      # If I had echoed `x` here, then the above line would have been a copy 
instead?
    
    proc ex2() =
      var x = MyObj()
      consume(x) # x is moved into consume right away?
      # an echo here would make the above line a copy of x instead?
    
    
    Run

What exactly is happening in memory on a move compared to copy in this case? Or 
are they basically the same in this case (except the move zeros the source)?

**Case 2:** Now let's introduce a object with a seq: 
    
    
    type
      MyObj = object
        children: seq[MyObj]
    
    proc consume(x: sink MyObj) =
      # Do something with it
      discard
    
    proc ex3() =
      var x = createLargeTree() # just creates a deep tree of nested MyObjs, 
the main thing is that it's big in memory
      var y = x
    
    proc ex4() =
      var x = createLargeTree() # just creates a deep tree of nested MyObjs, 
the main thing is that it's big in memory
      var y = x # now this is a copy
      consume(x) # x get's moved into consume
    
    
    Run

My question here is what's happening to the seq field in this case when x is 
moved. The thing that throws me off is that seqs has value semantics and are 
deeply copied on "copy" but it's in fact just a stack-pointer to memory on the 
heap. Depending on how seqs in objects are implemented I can see two ways a 
move could work:

  1. All the MyObj's fields are just copied directly like 
    
        y.field = x.field
    
    Run

which would mean that the value semantics of seqs come into play and the entire 
tree is copied along with the object.
  2. Arc is smart and knows how different fields should be treated. It knows 
that it should just copy the pointer of the seq and not the seq itself to avoid 
unneccecary copies.



If it's option 2 I think I'm starting to see why move semantics can be more 
efficient in some cases. A last question: Arc does sink parameter interference, 
right? Do I ever need to annotate my procs with "sink" or can I trust it to 
always move when I consume a variable at the end of a proc?

Hopefully my questions are fairly understandable and not too obvious. Thank you 
in advance! :-D 

Reply via email to