📚 Gaddis (Ch. 16.5)
“The Standard Template Library provides a set of well structured generic C++ components that work together in a seamless way.”
- Alexander Stepanov & Meng Lee, The Standard Template Library
vector
, list
, deque
set
, multiset
, map
, multimap
stack
, queue
, priority_queue
iterator
, const_iterator
, value_type
, etc.operator<
stack
, queue
, priority_queue
std::vector
STL’s std::vector
is essentially a dynamic array.
push_back()
and pop_back()
sequential (end) access.[]
)vector
s know their own size!std::vector
Exampleusing std::vector;
using std::string;
// [...]
vector<string> v; // create vector
v.push_back("The number is 10"); // push some values
v.push_back("The number is 20"); // into it...
v.push_back("The number is 30");
cout << "Loop by index:" << endl;
for(vector<string>::size_type i=0; // size type is unsigned
i < v.size(); // vector knows its size!
i++){ // print values by
cout << v[i] << endl; // indexing the
} // vector like an array
HINT: Use v.at(i)
instead of v[i]
to enable bounds-checking!
std::vector
Example 2std::vector<std::string> v; // create vector
v.push_back("The number is 10"); // push some values
v.push_back("The number is 20"); // into it...
v.push_back("The number is 30");
cout << "Loop by range using iterators:" << endl;
for(auto it = v.begin(); // iterator
it != v.end(); // runs from begin()
++it) // to end(), one at a time
{ // and is
cout << *it << endl; // dereferenced to
} // print the value
*
) is used to “follow the arrow” to get the value an iterator is pointing to.std::vector
Example 3std::vector<std::string> v; // create vector
v.push_back("The number is 10"); // push some values
v.push_back("The number is 20"); // into it...
v.push_back("The number is 30");
cout << "Loop by range-based `for`:" << endl;
for( auto item : v ){ // for each item in v
cout << item << endl; // print the item
}
std::vector
Example 4auto v = std::vector<std::string>{3}; // pre-size to 3
int n = 1;
for( auto& item : v){ // each item (by ref.)
item = std::string{"The number is "} // generate message
+ std::to_string(10 * n++); // and store in item
}
cout << "Loop by range:" << endl;
for( auto item : v ){ // for each item
cout << item << endl; // print the item
}
std::to_string()
is contained in <std::string>
Iterators are a generalization of pointers.
++
)++
and --
)vector
ModifiersThese are algorithms that vector
s know how to apply to themselves:
clear() : clears all contents (empties the container)
erase() : erase one element, given an iterator to it
insert() : inserts element before a position (given an iterator)
pop_back() : removes the last element
push_back() : adds a new element at the end
resize() : changes the size of the vector
[...] There are others not shown here
clear()
Empties the vector.
erase(it_target)
Erases the element pointed to by the iterator it_target
.
std::vector<int> v{4,8,15,16,23,42,108};
std::vector<int>::iterator target = v.begin();
// Move target to the third element:
target += 2; // by skipping the first two
v.erase(target); // erases the third element
for( auto value : v ){
std::cout << value << '\t';
}
4 8 16 23 42 108
insert( it_position, value )
Inserts value
at the position pointed to by the iterator it_position
, shifting current values \(\ge\) it_position
to the right.
std::vector<int> v{4,8,16,23,42,108};
v.insert(v.begin() + 2, 15); // insert before 16
for( auto value : v ){
std::cout << value << '\t';
}
4 8 15 16 23 42 108
pop_back( )
Removes the last value in the vector.
std::vector<int> v{4,8,15,16,23,42,108};
v.pop_back();
for( auto value : v ){
std::cout << value << '\t';
}
4 8 15 16 23 42
push_back( )
Adds a new value at the end.
std::vector<int> v{4,8,15,16,23,42};
v.push_back(108);
for( auto value : v ){
std::cout << value << '\t';
}
4 8 15 16 23 42 108
resize( )
Changes size of the vector. Use this to pre-allocate:
std::vector<int> v;
v.resize(10);
for(int i = 0; i < v.size(); ++i){
v.at(i) = (i+1);
}
for( auto value : v ){
std::cout << value << '\t';
}
1 2 3 4 5 6 7 8 9 10
vector
s to functionsstd::vector
is an object type, meaning that it is passed by value by default! This means that even though it “looks and feels” like an array, the argument-to-parameter communication mechanism is quite different.
Let’s look at an example…
Example: Vectors as parameters VS arrays as parameters
First, the “main” part of the program, which will utilize two overloaded functions:
#include <iostream>
#include <vector>
void example(int a[], int size);
void example(std::vector<int> v);
void print_all(int a[], int size);
void print_all(std::vector<int> v);
int main(){
int a[]{1, 2, 3, 4, 5};
std::vector<int> v {1, 2, 3, 4, 5};
example(a, 5);
example(v);
print_all(a, 5);
print_all(v);
return 0;
}
Example: Vectors as parameters VS arrays as parameters
void example(int a[], int size){
for(int i = 0; i < size; ++i)
a[i] *= 2;
}
void example(std::vector<int> v){
for(std::vector<int>::size_type i = 0; i < v.size(); ++i)
v[i] *= 2;
}
void print_all(int a[], int size){
for (int i = 0; i < size; ++i)
std::cout << a[i] << '\t';
std::cout << '\n';
}
void print_all(std::vector<int> v){
for(auto value : v)
std::cout << value << '\t';
std::cout << '\n';
}
Example: Vectors as parameters VS arrays as parameters
Here is the relevant part of the main program again…
What output do you expect from this code?
Example: Vectors as parameters VS arrays as parameters
Here is the output:
Is that what you expected?
The std::vector
is passed by value, so the elements are not modified in the caller (main
) even though they were modified in the example
function.
We can pass by reference if we want to. While we’re at it, let’s use const
qualifiers to add safety guarantees to the printing functions.
void example(int a[], int size){
for(int i = 0; i < size; ++i)
a[i] *= 2;
}
void example(std::vector<int>& v){
for(std::vector<int>::size_type i = 0; i < v.size(); ++i)
v[i] *= 2;
}
void print_all(const int a[], int size){
for (int i = 0; i < size; ++i)
std::cout << a[i] << '\t';
std::cout << '\n';
}
void print_all(const std::vector<int>& v){
for(auto value : v)
std::cout << value << '\t';
std::cout << '\n';
}
Now, the output - without changing main()
at all:
Hint: Prefer to pass a vector
(or other STL container) by const
reference (or plain reference if you want to modify it in the function) unless there is a “good reason” to make a copy.
STL and Vectors
CS 50x2 Accelerated Programming Series