# How to make a struct that contains a reference to other memory?

**URL:** https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195
**Category:** General Usage
**Tags:** memory-allocation
**Created:** [July 18, 2024, 6:17pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195 "2024-07-18T18:17:59Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![AwesomeQuest](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/awesomequest/32/38910_2.png) [@AwesomeQuest](https://discourse.julialang.org/u/AwesomeQuest)
#### Post date: [July 18, 2024, 6:18pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/1 "2024-07-18T18:18:00Z")

</div>

I have a vector of nodes, something like

```julia
struct Node
    x::Float64    
    # more fields
end
nodes = Vector{Node}(undef, bignumber)

```

And I have a vector of Elements that each contain some nodes

```julia
struct Element
    numNodes::UInt8
    tag::Int
    nodes::Vector{Node}
    # more fields
end
elems = [Element(n, i, nodes[inds]) for inds in indices]

```

This is terrible for size reasons, so my first thought is to use Ref since the manual makes it seem like the Julia version of pointers.

```julia
struct Element
    numNodes::UInt8
    tag::Int
    nodes::Vector{Ref{Node}}
    # more fields
end
elems = [Element(n, i, Ref.(nodes[inds])) for inds in indices]

```

But this doesn’t work, the only thing that seems to work is using SubArrays/Views

```julia
struct Element
    numNodes::UInt8
    tag::Int
    nodes::SubArray
    # more fields
end
elems = [Element(4,i,@view nodes[inds] #= etc =#) for inds in indices]

```

My question is then two fold:  
Is this the correct way of doing this or is there a better more performant way to do and think about this in Julia?  
How do you make a struct that contains a reference to another bit of memory? Since using a view would seem silly for something that isn’t an array.

P.S. Is a Ref not actually the Julia version of a Pointer?

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [July 18, 2024, 6:43pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/2 "2024-07-18T18:43:25Z")

</div>

Hi there!  
Can you give a complete MWE, and explain why the solutions you have “don’t work” or are “terrible”? In particular, it seems `indices` is a vector of vectors?

---

<div class="post-metadata">

### Author: ![AwesomeQuest](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/awesomequest/32/38910_2.png) [@AwesomeQuest](https://discourse.julialang.org/u/AwesomeQuest)
#### Post date: [July 18, 2024, 7:30pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/3 "2024-07-18T19:30:38Z")

</div>

MWE of Ref not working

```julia
julia> struct Foo
           y::Float64
       end

julia> struct Bar
           l::Int
           o::Vector{Ref{Foo}}
       end

julia> foos = [Foo(i) for i in 1:4]
4-element Vector{Foo}:
 Foo(1.0)
 Foo(2.0)
 Foo(3.0)
 Foo(4.0)

julia> bar = Bar(2, Ref.(foos[1:2]))
Bar(2, Ref{Foo}[Base.RefValue{Foo}(Foo(1.0)), Base.RefValue{Foo}(Foo(2.0))])

julia> foos[1] = Foo(5)
Foo(5.0)

julia> bar
Bar(2, Ref{Foo}[Base.RefValue{Foo}(Foo(1.0)), Base.RefValue{Foo}(Foo(2.0))])
# Foo(1.0) has not changed

```

The reason

```julia
struct Element
    numNodes::UInt8
    tag::Int
    nodes::Vector{Node}
    # more fields
end

```

is terrible is because in the case that you have many `Element`s referencing the same nodes you are copying the data of those nodes, thus this is a waste of memory.

Each `Element` could reference an arbitrary subset of `nodes` which is why `indices` is a vector of the indices of the nodes that each `Element` has.

My goal is to minimize memory usage since I could be making hundreds of thousands of `Node`s, each of which must belong to at least one `Element`.

From reading the manual it seems like one should be able to use `Ref` to reference another piece of memory like pointers do in C, am I mistaken?

I apologize for not giving a more thorough explanation.

---

<div class="post-metadata">

### Author: ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)
#### Post date: [July 18, 2024, 7:53pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/4 "2024-07-18T19:53:33Z")

</div>

> [@AwesomeQuest](#):
>
> `bar = Bar(2, Ref.(foos[1:2]))`

`foo[1:2]` makes a copy of the elements.  
What you want to use here is `bar = Bar(2, [Ref(foos, i) for i in 1:2])`. See the doc string of `Ref`.

Also note that

```julia-repl
julia> isabstracttype(Ref{Foo})
true

```

which will make iterating over this vector slow.  
You should instead use `Vector{Base.RefValue{Foo}}`.

* * *

> [@AwesomeQuest](#):
>
> From reading the manual it seems like one should be able to use `Ref` to reference another piece of memory like pointers do in C, am I mistaken?

Yes, they can be used that way.

But if you are dealing with arrays, I would recommend you to work with `view` and `SubArray`s instead.

E.g.

```julia-repl
julia> struct Bar{V<:AbstractVector{<:Foo}}
           l::Int
           o::V
       end

julia> bar = Bar(2, view(foos, 1:2))

```

---

<div class="post-metadata">

### Author: ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)
#### Post date: [July 18, 2024, 8:00pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/5 "2024-07-18T20:00:33Z")

</div>

You could make `Node` be a `mutable struct`. This way, putting some of them in an array doesn’t copy the content around, just a pointer.

Another solution is to use views. You already suggested this in your OP but didn’t really say why that’s a bad idea. Seems reasonable to me.

---

<div class="post-metadata">

### Author: ![AwesomeQuest](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/awesomequest/32/38910_2.png) [@AwesomeQuest](https://discourse.julialang.org/u/AwesomeQuest)
#### Post date: [July 18, 2024, 8:13pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/6 "2024-07-18T20:13:26Z")

</div>

Using views does make sense, though the context in how I’ve seen views used is very different from how I’ve seen pointers used on other languages (i.e. a way to avoid copying, rather than a data type in and of themselves).  
And I was wondering if there was a convention I was missing.

My main point of confusion was how different the syntax is when pointing to an array vs not an array (as shown by @fatteneder ). And I didn’t know that broadcasting made copies of the arguments.

---

<div class="post-metadata">

### Author: ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)
#### Post date: [July 18, 2024, 8:22pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/7 "2024-07-18T20:22:45Z")

</div>

> [@AwesomeQuest](#):
>
> And I didn’t know that broadcasting made copies of the arguments.

Not only broadcasting makes a copy.  
In the example above already slicing the array with `foos[1:2]` makes a copy. And then calling `Ref.(foos[1:2])` makes a second copy.

---

<div class="post-metadata">

### Author: ![AwesomeQuest](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/awesomequest/32/38910_2.png) [@AwesomeQuest](https://discourse.julialang.org/u/AwesomeQuest)
#### Post date: [July 18, 2024, 8:37pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/8 "2024-07-18T20:37:20Z")

</div>

Just one more question:  
Why `V<:AbstractVector{<:Foo}` and not `V<:SubArray`?  
Do these tell the compiler substantiality different things or is this a human readability choice?

---

<div class="post-metadata">

### Author: ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)
#### Post date: [July 18, 2024, 9:03pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/9 "2024-07-18T21:03:53Z")

</div>

Its more general.  
If you were to restrict to `V<:SubArray` you couldn’t call

```julia-repl
julia> bar = Bar(2, foo)

```

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [July 18, 2024, 9:13pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/10 "2024-07-18T21:13:38Z")

</div>

> [@AwesomeQuest](#):
>
> Why `V<:AbstractVector{<:Foo}` and not `V<:SubArray`?

There is almost never a performance benefit to tightening constraints on type parameters (unless maybe the constraint is a concrete type, but then it should not be a parameter). They are mostly just there for for their ability to add convenient guardrails against stuff going too crazy. They should mostly be unconstrained or constrained to broad, abstract types.

In your case, maybe there’s some world where a `NTuple{3,Foo}` would be reasonable in that parameter. Though this is not `<:AbstractVector{Foo}`, it meets most of the interface for it and would probably work for most things. There’s no cost to leaving this as a hypothetical possibility, so it’s nice to have it.

At runtime, you will have a `Bar{SubArray{<complete type parameterization to make a concrete type>)}}.` _This_ is what the compiler will actually specialize for. Since it specializes at that level, there isn’t real benefit to a tighter a-priori constraint.

---

<div class="post-metadata">

### Author: ![AwesomeQuest](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/awesomequest/32/38910_2.png) [@AwesomeQuest](https://discourse.julialang.org/u/AwesomeQuest)
#### Post date: [July 18, 2024, 9:33pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/11 "2024-07-18T21:33:32Z")

</div>

That brings up another thing I tried for the same project as this.

Is there a way to make something like

```julia
julia> struct Node
           dim::UInt8
           tag::UInt
           pos::NTuple{dim, Float64}
       end
ERROR: UndefVarError: `dim` not defined

```

Where the size of the `NTuple` is a parameter, like `Node{Dim}`? Or must one make many structs like

```julia
Node1D
Node2D
Node3D
...

```

And this would be to make the struct only use concrete types.

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [July 18, 2024, 9:46pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/12 "2024-07-18T21:46:44Z")

</div>

> [@AwesomeQuest](#):
>
> Is there a way to make something like

Yes. _EDIT: I wasn’t reading closely so originally left `dim` as a field._

```julia
struct Node{dim}
  tag::UInt
  pos::NTuple{dim, Float64}
end

```

```julia-repl
julia> fieldtype(Node{0}, :pos)
Tuple{}

julia> fieldtype(Node{1}, :pos)
Tuple{Float64}

julia> fieldtype(Node{2}, :pos)
Tuple{Float64, Float64}

julia> fieldtype(Node{3}, :pos)
Tuple{Float64, Float64, Float64}

```

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [July 20, 2024, 3:53pm UTC](https://discourse.julialang.org/t/how-to-make-a-struct-that-contains-a-reference-to-other-memory/117195/13 "2024-07-20T15:53:04Z")

</div>

But drop `dim` as a field in the struct. It should just be a type parameter. If I’m not mistaken, the `dim` field is now unconnected with the parameter, and also wholly redundant.

```julia
julia> x = Node{3}(2, 10, (1.0, 2.1, 3.2));

julia> x.dim
0x02

```
