# Does Julia have efficient move semantics?

**URL:** https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165
**Category:** New to Julia
**Tags:** question
**Created:** [November 2, 2024, 9:46am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165 "2024-11-02T09:46:51Z")
**Posts on this page:** 20
**Page:** 2

<div class="post-metadata">

### Author: ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)
#### Post date: [November 3, 2024, 4:12pm UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/22 "2024-11-03T16:12:00Z")

</div>

> [@Sukera](#):
>
> Generally, the way I think about variables in Julia is that they’re a label for some object.

It’s simpler to think of it in terms of the actual implementation.

It behaves the same way as Python, so I assume the implementation is roughly the same.

In Python, every object is a heap-allocated struct which looks a bit like this.

```julia
struct PyObject {
    PyType* type;
    (void*) data;
}

```

I don’t recall the full details or exact specification of this struct, but if you know this, you know enough to understand how everything works. Variables are `PyObject* my_var`, effectively.

Julia also has this optimization relating to immutable structs. But this is transparent to the user.

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [November 3, 2024, 4:18pm UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/23 "2024-11-03T16:18:14Z")

</div>

There is an example of a move in julia.

```julia
v = UInt8[65,66,67]
s = String(v)
# Now, the content of v is gone

```

Originally, I think it did not copy, but I’m not sure how that works now, I think it copies.  
It’s not too hard to implement such moving things via the `Vector`/`Memory` interface, but there is no standard syntax for it in julia.

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [November 3, 2024, 5:14pm UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/24 "2024-11-03T17:14:08Z")

</div>

> [@world-peace](#):
>
> > [@Sukera](#):
> >
> > Generally, the way I think about variables in Julia is that they’re a label for some object.
> 
> It’s simpler to think of it in terms of the actual implementation.
> 
> It behaves the same way as Python, so I assume the implementation is roughly the same.

Ah, you assume. And the developers of julia you’re discussing such details with don’t really have the right understanding of julia?

No, a variable in julia is not like in python. It’s not typically some memory chunk which is filled with a pointer to a vector for some time, and a pointer to a string, or int or whatever later. While this is approximately correct for top level variables (i.e. in Main or whatever module), that’s not the typical julia variable. Think of them as labels, entities referencing some value. The compiler will do all sorts of transformations, like creating SSA IR, and it’s not assumed that there is some memory chunk corresponding to the variable.

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [November 4, 2024, 2:19am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/25 "2024-11-04T02:19:30Z")

</div>

> [@sgaure](#):
>
> Originally, I think it did not copy, but I’m not sure how that works now, I think it copies.

It copies unless `v` was allocated specially (by `Base.StringVector(n)`).

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [November 4, 2024, 7:46am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/26 "2024-11-04T07:46:18Z")

</div>

> [@world-peace](#):
>
> It behaves the same way as Python, so I assume the implementation is roughly the same.
> 
> In Python, every object is a heap-allocated struct which looks a bit like this.

The abstract concepts of variables are definitely in the same ballpark, in a different town from that of C/C++/Rust; there are differences in scoping behavior and one big one I’ll explain later. Definitely not implemented the same. Allocating every object on the heap is one of the reasons that Python is considered “bad” for performance, though it’s worth noting that practical Python has good ways to evade it in other languages. Julia generally stack allocates technically immutable instances (primitives and `Tuple`s or `struct`s thereof) and generally copies them around, but the compiler has leeway on what really happens because none of these are language-level details. That doesn’t necessarily line up with practical mutability; `String`s cannot be mutated but they are technically a mutable type, while we can use mutating methods on a technically immutable `SubArray` to change its data stored in its contained mutable parent array.

> [@jling](#):
>
> > [@Vasily\_Pisarev](#):
> >
> > Julia is strictly pass-by-value language
> 
> depends on your definition, but it’s more commonly referred to as pass-by-sharing

I’ve found these concepts confusing and needlessly relative to other languages with vastly different concepts variable, though part of the documented description of pass-by-sharing gets to the point: the variables in the method are assigned to the _same_ instances in the method call. The confusing part is the assertion that “values are not copied when they are passed to functions”, which is only true in a trivial sense that an instance is itself. C/C++/Rust users probably see that phrase and think of data being copied into the stack frame, and that happens all the time. It’s just that on a language level, equal immutable instances (`==`) are the same instance (`===`); you could instantiate or `copy` the same immutable value 1000 times, you only ever had 1 instance, even if they’re reasonably implemented as scattered data copies. This only sorta happens in Python with object caching; otherwise, its heap-allocated objects with separate addresses must be distinguished as different instances. That is also generally the case for mutables in Julia, though `String` is a notable exception for reasons I still don’t know.

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [November 4, 2024, 8:53am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/27 "2024-11-04T08:53:22Z")

</div>

> [@Benny](#):
>
> That is also generally the case for mutables in Julia, though `String` is a notable exception for reasons I still don’t know.

`String`s should have been immutable, they behave as immutable, but for technical reasons they are not, though there is no way to mutate them. Egal comparisons (`===`) between them therefore end up in a memcp here: [julia/src/builtins.c at master · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/blob/master/src/builtins.c#L253-L258)  
Ideally, two strings with the same content should have the same address, but that would incur a search through existing strings whenever a string is created. (I think R does that, but I haven’t been in there for some years).

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [November 4, 2024, 9:14am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/28 "2024-11-04T09:14:32Z")

</div>

> [@sgaure](#):
>
> they behave as immutable, but for technical reasons they are not, though there is no way to mutate them

Yeah with the `===` implementation, I don’t know why they aren’t also just exposed as immutable (according to `ismutabletype` anyway) on a language level, and we just have to know that it’s heap allocated due to its unfixed size. I just assume that if I do bother to dig into it, I’ll fail to come up with a good way to do that.

> [@sgaure](#):
>
> Ideally, two strings with the same content should have the same address

Is this the same as interning? `Symbol`s do that, though I don’t know how those are implemented either considering there’s so many of them in parsing.

---

<div class="post-metadata">

### Author: ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)
#### Post date: [November 4, 2024, 9:57am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/29 "2024-11-04T09:57:12Z")

</div>

> [@sgaure](#):
>
> There is an example of a move in julia.
> 
> ```julia
> v = UInt8[65,66,67]
> s = String(v)
> # Now, the content of v is gone
> 
> ```

We should probably disambiguate two things

- What you show here is more like a “consume” operation. The data from the input is indeed gone, just like a move semantic, but because you have converted from one data type to another, this isn’t quite the same as the highly efficient “move” where some pointers/references/whatever you want to call them are swapped.
- The “efficient move” semantic I really intended was closer to this from C++ `std::move(x)`. It’s a bit tricky to explain what that does in a sentence or two. On a technical level, it tells the compiler `x` is an “xvalue expression” which means expiring value. A simpler explanation is it tells the compiler you won’t be using the data referred to by `x` anymore. This can cause the compiler to use things like move constructors in expressions like `y = SomeType(std::move(x))`, if they exist.

> [@sgaure](#):
>
> No, a variable in julia is not like in python.

If you _ **read** _ what I said:

> [@world-peace](#):
>
> It behaves the same way as Python, so I assume the implementation is roughly the same.

The point being, it does not matter what the exact implementation is, because the _behavior_ is the same.

If you can demonstrate an example of how two types (eg a list/array or something) behave differently between Julia and Python, please go ahead… If there are relevant behavioral differences, then it would be interesting to hear about them.

Yes, Julia and Python are different because Julia is compiled using LLVM and Python is compiled to bytecode which is then interpreted. But this is a totally pointless statement and irrelevant to the whole thread, because it doesn’t say anything about how they differ from the point of view of a user.

~~My point being: Don’t just say “no you’re wrong” and then proceed to either agree or just go on an irrelevant tangent.~~

Edit: I re-read your comments and I think your point is Julia is able to optimize away some of the things you would can’t optimize away in Python, such as everything being allocated on the heap. Therefore there is a behavioral difference in terms of the _performance_. Fair enough, but that wasn’t the point of this discussion. We already know the performance of Python is bad compared to compiled languages.

> [@Benny](#):
>
> Julia generally stack allocates technically immutable instances

You may have missed this earlier comment. That’s what I’m referring to here…

> [@world-peace](#):
>
> Julia also has this optimization relating to immutable structs. But this is transparent to the user.

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [November 4, 2024, 10:29am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/30 "2024-11-04T10:29:11Z")

</div>

> [@world-peace](#):
>
> The point being, it does not matter what the exact implementation is, because the _behavior_ is the same.

Your whole point was that you view julia variables like python variables because they behave in the same way. I.e. a variable is a type descriptor and a data pointer.

This is not good advice. Such a mental model for julia variables will make the performance hints in the manual very hard to understand. And, after all, performance is one of the strong properties of julia. The whole point of making your functions type stable is that the types then exist only in the compiler, not at run time. This is also the reason why one should avoid abstract field types in structs, in particular abstract element types in `Vector`s.

---

<div class="post-metadata">

### Author: ![barucden](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barucden/32/26154_2.png) [@barucden](https://discourse.julialang.org/u/barucden)
#### Post date: [November 4, 2024, 10:48am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/31 "2024-11-04T10:48:12Z")

</div>

Have you received a satisfactory answer to your question? I still can’t tell what exactly it is that you are asking.

Is there a `std::move` in Julia? No, there isn’t. Julia’s memory model is different to C++ (@foobar_lv2’s answer had many good points). Is there a way to mimic `std::move`? Yes, there is to some extent (see the `Ref` examples).

Could you post a snippet in C++ (or any language) that shows what you want to do? That might be the best way to get a good, definite answer. [Unless you look for countless arguments about the (dis)similarities between Julia and Python and C/C++, which rarely end in meaningful conclusions. We’ve had many such threads here.]

---

<div class="post-metadata">

### Author: ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)
#### Post date: [November 4, 2024, 10:49am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/32 "2024-11-04T10:49:04Z")

</div>

> [@world-peace](#):
>
> Does Julia have efficient move semantics?
> 
> Consider the following example, which is a stupid example, but it’s also a simple example.
> 
> ```julia
> v::Vector{String} = [some stuff]
> 
> function does_a_move_operation(v::Vector{T})::Vector{T} where T
> t::Vector{T} = []
> while length(v) > 0
> element = pop!(v)
> push!(t, element)
> end
> return t
> end
> 
> ```
> 
> This function is O(N). But it could have been O(1), if there were some efficient way to move the memory referenced by `v` to `t`

This was my original question.

> [@sgaure](#):
>
> Such a mental model for julia variables will make the performance hints in the manual very hard to understand. And, after all, performance is one of the strong properties of julia. The whole point of making your functions type stable is that the types then exist only in the compiler, not at run time. This is also the reason why one should avoid abstract field types in structs, in particular abstract element types in `Vector`s.

This has nothing to do with what is being discussed here.

---

<div class="post-metadata">

### Author: ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)
#### Post date: [November 4, 2024, 10:52am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/33 "2024-11-04T10:52:58Z")

</div>

> [@world-peace](#):
>
> > [@foobar\_lv2](#):
> >
> > ```julia
> > swap(&v1, &v2);
> > 
> > ```
> 
> This is a move. It also conforms to the semantics which I specified.

Ok, I think I understand your misconception now. In julia, local variables don’t have addresses. Instead they are “bindings” that refer to an object.

So, how would you do the swap?

Since local variables have no address, you must explicitly allocate the memory / slot for them, and then you pass this slot to the swap function:

```julia
a=Ref(4)
b=Ref(5)
swap(a,b)

```

In many cases this will boil down to the same machine-code as the C variant. In some cases it will be more like:

```julia
uint64_t* a = malloc(8);
uint64_t* b = malloc(8);
*a = 4;
*b = 5;
swap(a,b);

```

The reason is that the heap alloc can only be elided if `a` and `b` don’t escape due to the `swap` call. In C it doesn’t escape on pain of UB; in Rust, there are all the complex borrowing rules to ensure that it doesn’t escape; in julia, the compiler makes a best-effort to figure out whether the references escape, and when in doubt then a heap allocation is made.

> [@stevengj](#):
>
> It copies unless `v` was allocated specially (by `Base.StringVector(n)`).

Unfortunately it is quite buggy:

```julia
julia> function foo()
       v=UInt8[0x41 for i=1:801];
       popfirst!(v)
       vv=reshape(v, (800, 1))
       vvv = reshape(vv, (800,))
       s = String(vvv)
       Ref(s)
       end
foo (generic function with 1 method)

julia> foo()
Base.RefValue{String}(UInt8[0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 … 0x41, 0x41, 0x00, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41])

```

This clearly leads to a type confusion which will blow up everything.

I couldn’t see a way to finagle the confused writes in [julia/src/genericmemory.c at 9a77240f6f81b9d5999d40fdf5e2b6bb84e36783 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/blob/9a77240f6f81b9d5999d40fdf5e2b6bb84e36783/src/genericmemory.c#L185) into a good primitive for exploitation, though.

PS. [Type confusion with jl\_genericmemory\_to\_string · Issue #56435 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/56435)

---

<div class="post-metadata">

### Author: ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)
#### Post date: [November 4, 2024, 10:59am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/34 "2024-11-04T10:59:16Z")

</div>

Yes, of course. Approximately this (please excuse any syntax errors, I’m doing this entirely from memory from a machine which does not have a C++ compiler)

```julia
void moveVector(std::vector<double>* &v1, std::vector<double>* &v2) {
    std::vector<double> *tmp = v1;
    v1 = v2;
    v2 = tmp;
}

int main() {
    std::vector<double> v1 = std::vector<double>();
    std::vector<double> v2 = std::vector<double>();
    for(std::size_t i = 0; i < 1000; ++ i) {
        v2.push_back(0.0);
    }
    std::vector<double> *v1p = &v1;
    std::vector<double> *v2p = &v2;
    moveVector(v1p, v2p);
}

```

Assuming I didn’t mess that up, it is probably the most simple example. I avoided writing an example in terms of `std::move`, although this would have been easier. I didn’t choose that route because it is opaque if you don’t have a detailed understanding of how `std::move` works.

Let me know if I made a mistake, it’s been a number of years since I wrote C++ day to day.

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [November 4, 2024, 11:06am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/35 "2024-11-04T11:06:55Z")

</div>

I suggest the following:

```julia
v1 = fill(0.0, 1000)
v2 = fill(1.0, 1000)

v1, v2 = v2, v1

```

---

<div class="post-metadata">

### Author: ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)
#### Post date: [November 4, 2024, 11:16am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/36 "2024-11-04T11:16:42Z")

</div>

> [@world-peace](#):
>
> ```julia
> v1 = v2;
> v1 = tmp;
> 
> ```

Is that second line supposed to be `v2 = tmp`?

---

<div class="post-metadata">

### Author: ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)
#### Post date: [November 4, 2024, 11:34am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/37 "2024-11-04T11:34:19Z")

</div>

Good spot - edited

---

<div class="post-metadata">

### Author: ![world-peace](https://avatars.discourse-cdn.com/v4/letter/w/9f8e36/32.png) [@world-peace](https://discourse.julialang.org/u/world-peace)
#### Post date: [November 4, 2024, 11:35am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/38 "2024-11-04T11:35:53Z")

</div>

You really are having a hard time with this…

```julia
julia> v1=[1,2,3]
3-element Vector{Int64}:
 1
 2
 3

julia> v2=[4,5,6]
3-element Vector{Int64}:
 4
 5
 6

julia> function testIt(v1,v2)
       v2,v1=v1,v2
       end
testIt (generic function with 1 method)

julia> testIt(v1,v2)
([1, 2, 3], [4, 5, 6])

julia> println(v1)
[1, 2, 3]

```

---

<div class="post-metadata">

### Author: ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)
#### Post date: [November 4, 2024, 11:46am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/39 "2024-11-04T11:46:01Z")

</div>

You can do

```julia
julia> function testIt(v1,v2)
       tmp_r = v1.ref
       tmp_sz = v1.size
       setfield!(v1, :ref, v2.ref)
       setfield!(v1, :size, v2.size)
       setfield!(v2, :ref, tmp_r)
       setfield!(v2, :size, tmp_sz)
       nothing
       end
testIt (generic function with 1 method)
julia> v1=[1,2,3]; v2=[1]; testIt(v1,v2); @show v1,v2;
(v1, v2) = ([1], [1, 2, 3])

```

Note that this is somewhat unsafe – you’re not really supposed to do that. Especially this probably elevates concurrency bugs from “best-effort constrained bug” to “lol heap corruption, pop a shell”.

---

<div class="post-metadata">

### Author: ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)
#### Post date: [November 4, 2024, 11:46am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/40 "2024-11-04T11:46:04Z")

</div>

> [@world-peace](#):
>
> ```julia
> function testIt(v1,v2)
> v2,v1=v1,v2
> end
> testIt (generic function with 1 method)
> 
> julia> testIt(v1,v2)
> ([1, 2, 3], [4, 5, 6])
> 
> ```

Variables in julia are not chunks of memory where you can store things, they are names with a scope. The names `v1` and `v2` inside `testIt` are not the same names as outside, they merely refer to the same values/objects. You don’t have access to the outside names `v1` and `v2` inside `testIt`, unless you annotate with `global`.

But you can ditch the whole function, and just do `v1, v2 = v2, v1`.

---

<div class="post-metadata">

### Author: ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)
#### Post date: [November 4, 2024, 11:56am UTC](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165/41 "2024-11-04T11:56:06Z")

</div>

> [@world-peace](#):
>
> I didn’t choose that route because it is opaque if you don’t have a detailed understanding of how `std::move` works.

And I have the feeling that you don’t understand `std::move`. That is entirely about the transfer of unique ownership for the sense of resource management / RAII! And since julia and C don’t have unique ownership / RAII, `std::move` makes no sense.

Your example works in pure C and has nothing to do with C++. The crucial thing you did here was to take the address of a local variable. The difference is that julia local variables have no addresses! So you must explicitly create a slot/container, and then swap contents; whereas in C, the slot/container is created automagically by the compiler if it sees that the address of a local variable is taken.

[Previous page](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165.md?page=1)

[Next page](https://discourse.julialang.org/t/does-julia-have-efficient-move-semantics/122165.md?page=3)
