Function to add and change elements in a vector


#1

Hi all,

I’m trying to write a simple function to add and possibly modify elements added to a vector:

struct S {
   a: u32,
   b: u32
}

fn add(v: &mut Vec<S>, s: &mut S) {
   // dummy assignment
   s.a = 1;
   s.b = 2;

   // add element to vector
   v.push(s);
}

But v.push() needs a S structure, not a &mut S and the compiler gives an error. So what is the right way to code such a function ?

Thanks for your help.


#2

Pass ‘s’ by mut value to add(), not by reference.


#3

Thanks, it works great.

But doing that, I can’t use the ‘s’ variable because (I’m just learning Rust, so sorry if I’m wrong) it will be moved by the add fn, right ?


#4

Right - caller of add gives up ownership. It seems like that’s what you want since you have a Vec<S> rather than a Vec<&S>? In other words, do you want the Vec to own the S's or borrow them (i.e. hold references to them)?


#5

So if I give up ownership on ‘s’, I can use Vec<S> but if not, I have to use Vec<&S> ?


#6

Yup. Vec<S> says the vec owns the S values. You can then borrow them from the vec, immutably or mutably, but the Vec is the owner.

If you were to make it a Vec<&S>, that says the vec doesn’t own the S values, but is instead borrowing them from some other owner.

It might be easier to suggest the right approach if you provide more context, unless this is just a simple exercise without more context? :slight_smile:


#7

It was originally meant to determine the best way to add structures to vector, in the following context:

  • a struct A reads an XML file and create some other structures struct S from XML data
  • and push those structures into a vector (field of A)

Afterwards, I thought it should be useful to make this add function generic, to allow any struct to be added to a vector. But it seems in Rust, the overall context is important (whether or not relinquish ownership)


#8

Right - whether a vector owns the values or holds references to values or holds something like Rc (and thus shares ownership) are all important.

In your description above, it would seem like you’d want the vector to hold the parsed data (S values) and then other code can use that vector to borrow these values if needed.


#9

Yes, the more I discover Rust, the more I understand it that way.

Thanks a lot for your time :slight_smile:


#10

Another detail with knowing in this case is, is S large? If not, then you may want to just copy the data, so that no transfer of ownership needs to occur.

If you derive the Copy trait then it will be automatically copied when used by value (like primitive types are).

Also on that page you can see the Clone trait, which is for explicit copies. If you #[derive(Clone)] (which almost all types should) then x.clone() creates a copy.


#11

Yes, I knew I could use the Copy trait, but I wanted to exercise a little mutability and borrowing.

S struct is not large, but I want to understand how structures defined on the stack as locals are copied in the heap when pushed on a vector.