Step 2 of 6
Loop over a vector
Looping over a vector is best done with a range-based for. The reference symbol decides whether you get copies or the real elements:
for (auto x : v) // x is a copy of each element
for (const auto& x : v) // x refers to each element, read-only: no copies
for (auto& x : v) // x refers to each element, and you can modify it
For int the copy is cheap, but for strings or objects, const auto& avoids copying every element. Use auto& when you want to change the vector's elements in place.
#include <iostream>
#include <vector>
std::vector<double> scaled(const std::vector<double>& v, double k) {
std::vector<double> out;
out.reserve(v.size());
for (double x : v) {
out.push_back(x * k);
}
return out;
}
int main() {
std::vector<double> prices = {1.5, 2.0, 4.25};
for (auto& p : prices) p += 1;
std::vector<double> doubled = scaled(prices, 2);
for (const auto& p : doubled) std::cout << p << " ";
std::cout << "\n";
}
5 6 10.5
Passing and returning vectors
- Take a vector parameter by
const&when the function only reads it; by value would copy every element. - Take it by
&when the function must modify the caller's vector. - Return a new vector by value freely. Modern C++ moves (or directly constructs) the result instead of copying it, so returning even a large vector is cheap. You'll see why in the move semantics module.
out.reserve(n) sets the capacity up front when you know the final size, so push_back never has to reallocate.
Your turn: write std::vector<int> running_total(const std::vector<int>& v) that returns the prefix sums. {1, 2, 3, 4} becomes {1, 3, 6, 10}.