std::vector
A C++ array has a fixed size. std::vector is an array that grows and shrinks as you need, keeps track of its own size, and frees its memory when it goes out of scope. It's the container you'll reach for first.
Adding and reading elements
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> scores; // an empty vector of ints
scores.push_back(82);
scores.push_back(95);
scores.push_back(77);
cout << "size: " << scores.size() << endl;
cout << "first: " << scores[0] << ", last: " << scores.back() << endl;
for (int s : scores) cout << s << " ";
cout << endl;
return 0;
}size: 3
first: 82, last: 77
82 95 77 vector<int>says what the vector holds; any type works:vector<string>,vector<double>, even vectors of your own classes.push_backadds to the end, and the vector makes room by itself.size()counts the elements;front()andback()are the first and last.
at() checks, [] doesn't
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<string> names = {"Asha", "Leo", "Mei"};
cout << names.at(1) << endl;
try {
cout << names.at(5) << endl;
} catch (const out_of_range& e) {
cout << "Index 5 is out of range" << endl;
}
return 0;
}Leo
Index 5 is out of rangeA vector can start with values in braces. names[5] on a three-element vector reads memory that isn't part of it: undefined behaviour, which might print rubbish or crash. at(5) checks the index and throws an out_of_range exception you can catch. Use at while learning, and whenever an index comes from outside your code.
Vectors and functions
#include <iostream>
#include <vector>
using namespace std;
double average(const vector<double>& v) { // const&: read without copying
if (v.empty()) return 0;
double sum = 0;
for (double x : v) sum += x;
return sum / v.size();
}
void addBonus(vector<double>& v, double bonus) { // &: change the caller's vector
for (double& x : v) x += bonus;
}
int main() {
vector<double> marks = {72, 88.5, 64, 91};
cout << average(marks) << endl;
addBonus(marks, 5);
cout << average(marks) << endl;
for (double m : marks) cout << m << " ";
cout << endl;
return 0;
}78.875
83.875
77 93.5 69 96 Pass a vector by const& to read it and by & to change it. Passing it by value would copy every element on each call.
Inserting and removing
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {10, 20, 30, 40, 50};
v.erase(v.begin() + 1); // remove the element at index 1
v.insert(v.begin(), 5); // put 5 at the front
v.pop_back(); // drop the last element
for (int x : v) cout << x << " ";
cout << endl;
cout << (v.empty() ? "empty" : "not empty") << ", size " << v.size() << endl;
v.clear();
cout << "after clear: " << v.size() << endl;
return 0;
}5 10 30 40
not empty, size 4
after clear: 0v.begin() is an iterator, a position in the vector; v.begin() + 1 is the second element. Adding or removing at the end is fast. In the middle, every later element must shift along, so that's slower for long vectors.
Reading until the input ends
This example's input is 4 8 15 16 23 42:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums;
int x;
while (cin >> x) nums.push_back(x); // stops when there's no more input
int largest = nums[0];
for (int n : nums) if (n > largest) largest = n;
cout << "Read " << nums.size() << " numbers. The largest is " << largest << "." << endl;
return 0;
}Read 6 numbers. The largest is 42.cin >> x is false once the input runs out, so the loop reads however many numbers there are. A vector is the natural place to keep them.
A grid: vectors of vectors
#include <iomanip>
#include <iostream>
#include <vector>
using namespace std;
int main() {
int rows = 3, cols = 4;
vector<vector<int>> grid(rows, vector<int>(cols, 0)); // 3 rows of 4 zeros
for (int r = 0; r < rows; r++)
for (int c = 0; c < cols; c++)
grid[r][c] = r * cols + c;
for (const auto& row : grid) {
for (int x : row) cout << setw(4) << x;
cout << endl;
}
return 0;
} 0 1 2 3
4 5 6 7
8 9 10 11vector<int>(cols, 0) makes a row of cols zeros, and the outer vector holds rows copies of it. grid[r][c] then works like a 2D array, except the sizes can be chosen while the program runs.