Vectors in C++ are passed by value by default, which means the entire vector gets copied
When you pass a vector to a function in C++ without using a reference symbol, the program creates a complete copy of that vector. This copy includes all the data inside it — every element, every byte. The original vector in your calling code stays untouched, and the function works on the duplicate instead.
This is different from passing a pointer or a reference. With a reference, you pass a direct link to the original vector, not a copy. The function can read and modify the actual vector you sent, and those changes persist after the function ends.
Understanding this distinction matters because copying a large vector wastes memory and processing time. If you have a vector with thousands of elements and you pass it to ten different functions without using references, you now have eleven copies of that data in memory.
Key Takeaways
- Passing a vector without the & symbol creates a full copy of the vector and all its contents.
- Passing a vector with const vector<type>& lets the function read the original without copying or changing it.
- Passing a vector with vector<type>& (no const) lets the function modify the original vector directly.
- For large vectors, using references instead of copies can significantly reduce memory use and speed up your program.
Pass by value: when a copy is created
When you write a function signature like void processVector(vector<int> vec), you are declaring pass by value. The function receives a brand-new vector object that contains the same elements as the one you passed in, but it is a separate object in memory.
Any changes the function makes to vec — adding elements, removing elements, changing values — only affect the copy. The original vector in your calling code remains exactly as it was. This is safe because the function cannot accidentally damage your data, but it is expensive in terms of memory and CPU time.
Pass by value is useful when you want the function to work on a vector without any risk of side effects. It is also the default behavior, so if you do not add the & symbol, this is what happens.
Pass by reference: linking to the original vector
When you write void processVector(vector<int>& vec), the & symbol means the function receives a reference to the original vector, not a copy. The function can read every element and modify the vector directly. Any changes persist after the function returns.
References are faster and use less memory because no copying occurs. The function works on the actual vector you passed in. This is why references are the standard choice for functions that need to read or write large data structures.
The trade-off is that the function can now change your original vector. If that is not what you want, you need to add const to prevent modifications.
Pass by const reference: read-only access to the original
When you write void processVector(const vector<int>& vec), you get the speed and memory efficiency of a reference without the risk. The function can read every element of the original vector, but the const keyword prevents the function from changing anything.
This is the most common pattern for functions that only need to examine a vector. It avoids the cost of copying while guaranteeing that your original data stays unchanged. The compiler will reject any attempt inside the function to modify vec.
If you write a function that takes a vector but does not need to change it, using const vector<type>& is the right choice. It tells other programmers reading your code that this function is safe to call — it will not alter the vector you pass in.
Comparing the three approaches side by side
| Function Signature | What Happens | Memory Cost | Can Modify Original? | When to Use |
|---|---|---|---|---|
| void func(vector<int> vec) | Full copy created | High — entire vector copied | No | Small vectors or when you need a working copy |
| void func(vector<int>& vec) | Reference to original | Low — no copy | Yes | Function needs to read and change the vector |
| void func(const vector<int>& vec) | Reference to original | Low — no copy | No | Function only reads the vector (most common) |
Real performance differences with large vectors
The cost of pass by value grows with the size of the vector. A vector with 10 elements copies quickly. A vector with 10 million elements takes measurable time and memory to copy.
If you have a function that receives a large vector and calls another function that also receives the same vector by value, you now have multiple copies in memory at the same time. Each copy consumes space and takes CPU cycles to create and destroy.
Using references eliminates this overhead. The function receives a direct link to the original data and can work with it when ready. For programs that process large amounts of data — image processing, data analysis, scientific computing — this difference is often the reason a program runs in seconds versus minutes.
Common mistakes when passing vectors
A frequent mistake is forgetting the & when you want to modify a vector inside a function. If you write void addElement(vector<int> vec) and then add an element inside the function, the element is added to the copy, not the original. The calling code sees no change.
Another mistake is using pass by value for large vectors when you only need to read them. This wastes memory and slows the program down. If a function does not modify the vector, use const vector<type>&.
A third mistake is assuming that references are always faster. For very small vectors, the overhead of creating a reference might be comparable to copying, though references are still the safer choice. The real win comes with vectors that contain hundreds or thousands of elements.
Frequently Asked Questions
If I pass a vector by reference and the function crashes, will my original vector be corrupted?
Not from the crash itself, but if the function was modifying the vector when it crashed, those partial changes may persist. Using const vector<type>& prevents the function from making any changes at all, so this risk does not explore. If you need the function to modify the vector, you accept this risk as part of using references.
Should I always use const reference for reading vectors?
Yes, unless you have a specific reason not to. const vector<type>& is fast, safe, and tells other programmers that the function does not change the vector. It is the standard practice in C++ code.
What if I want to return a modified vector from a function?
Return it by value: vector<int> processVector(const vector<int>& input). The function receives the input by const reference (no copy), does its work, and returns a new vector. Modern C++ compilers optimize this with move semantics, so the return is efficient even though it looks like a copy.
Can I pass a vector to a function that expects a pointer instead of a reference?
Yes, but you need to use the address-of operator: processVector(&vec). Inside the function, you would declare it as void processVector(vector<int>* vec) and access elements with vec->at(0) instead of vec[0]. References are cleaner and more common in modern C++.
Does using a reference mean the vector cannot be destroyed while the function runs?
Correct. The original vector must stay in memory for the entire time the function is using the reference. If the vector is destroyed before the function ends, the reference becomes invalid and the program will crash. This is why references should only be used for function calls where the vector outlives the function.