126. Vec::split_off — Cut a Vec in Two and Keep Both Halves
You want the tail of a Vec as its own owned collection — the head stays put, the tail walks away. Cloning a slice works for Clone types, but breaks the moment your elements aren’t cloneable. Vec::split_off doesn’t care.
The clone-and-truncate dance
The textbook split: copy the tail with to_vec(), then truncate the original.
| |
It works, but it clones every element of the tail. Fine for i32, wasteful for String, and a hard error for any type that isn’t Clone.
split_off moves, doesn’t clone
Vec::split_off(at) consumes the elements at at.. out of the original Vec and returns them as a new Vec. The elements are moved, not copied — so it works for any T, Clone or not:
| |
The original keeps [0..at), the returned Vec gets [at..len), and not a single element is duplicated. at == 0 gives you the whole thing in the new Vec (the original ends up empty); at == len gives you an empty new Vec. Anything past the length panics.
A real shape: page-by-page draining
split_off shines when you want to peel a batch off the front of a queue and hand it to a worker, keeping the rest for next time:
| |
No clone, no temporary Vec, no fighting the borrow checker over slice ranges. Two memcpys and you’re done.
When to reach for it
Use split_off whenever you need both halves of a Vec as owned collections — batching, chunked processing, splitting state between threads. If you only want to iterate the tail and throw it away, drain(at..) is better; if you want to keep it, split_off is the move.