Home > Software engineering >  Rust lifetime of string slices within a vector within a struct
Rust lifetime of string slices within a vector within a struct

Time:06-29

While writing a program of mine, I came across a structure containing a vector of strings. My (basic) knowledge of Rust led me to wonder whether a Vec<&str> within a structure like this:

struct StrSliceVector<'a> {
    v: Vec<&'a str>
}

(that has the lifetime strongly related to the structure) is more efficient or allocates less heap-memory than this one:

struct StringVector {
    v: Vec<String>
}

I imagine that since in StringVector the Strings are allocated in the heap, then it would result in a vector (also in the heap) containing pointers to other memory locations with the actual strings. Does StrSliceVector allocate the strings internally to the vector heap-space?

CodePudding user response:

When you create the Vec<String>, you must decide whether you wish to move existing Strings into the vector, or clone them in. If you move them in then no additional heap allocations are required, so it's the same total heap allocations as Vec<&'a str> from this point of view. Which is more appropriate depends on your use case. What do you wish to do with the elements of the vector?

If you don't require ownership of the strings in the vector for the operations you intend to perform, the string slice version should be your first instinct as it means the strings are still available for manipulation elsewhere in the code, after the vector has been dropped.

CodePudding user response:

A &str takes up two usizes of memory (not including the string data its referencing) while a String takes up three usizes. But if this matters to you, then you can replace String with Box<str> to get the same size as a &str just as an owned version. Then you're back at simply looking at the logical difference of "owned" vs "borrowed".

A &str only references existing data, while the String owns its data. The only reason that the String version would take significantly more memory than &str would be if the strings are already owned elsewhere: in another structure or from a string literal, for example. If they are, then you're just copying what already exists, therefore using more memory. If you want a datatype that can handle both owned and borrowed data to save on allocations, consider using a Cow.

Does StrSliceVector allocate the strings internally to the vector heap-space?

Both are &str and String are similar that in-place they are basically just pointers; the data will always exist elsewhere and not in-line with the Vec elements.

So in broad terms, &str will be more space-efficient, but lifetimes introduce more constraints that may make StrSliceVector<'a> unviable depending on how you intend to use it. Since references don't own their data, you must ensure that whatver does own the strings keeps them alive as long as you are using the vector.

  • Related