It’s useful if you have an idea how many elements the vector will ultimately hold – it can help the vector avoid repeatedly allocating memory (and having to move the data to the new memory).
In general it’s probably a potential optimization that you shouldn’t need to worry about, but it’s not harmful either (at worst you end up wasting memory if you over estimate).
One area where it can be more than an optimization is when you want to ensure that existing iterators do not get invalidated by adding new elements.
For example, a
push_back() call may invalidate existing iterators to the vector (if a reallocation occurs). However if you’ve reserved enough elements you can ensure that the reallocation will not occur. This is a technique that doesn’t need to be used very often though.