Home

 › 

Articles

 › 

Vector In C++ STL Explained, With Examples

Vector in C++ STL

Vector In C++ STL Explained, With Examples

The Standard Template Library (STL) in C++ is one of the most commonly used libraries. STL provides a lot of algorithms and data structures, helping to simplify the process of developing code.

Within the STL, the vector is one of the most popular data structures and has some benefits over a conventional array. Read on to discover exactly how vectors in C++ work and how they can be used.

What Are Vectors In C++ STL?

Simply put, a vector is a type of data structure known as a dynamic array. This differs from a more traditional array in that a vector’s size can be changed during execution. This is what makes vectors a dynamic structure.

As such, vectors are most helpful when you need to store elements and adjust their size over time. It should be noted that vectors always contain elements of an identical data type, such as strings or integers.

Vectors also have the advantage of being able to be traversed using iterators, since their elements are stored contiguously.

How Do You Use Vectors?

vector in C++ stl
Declaring a variable in order to create a vector.

©History-Computer.com

To use vectors, you must include the “vector” header file, as this is the file within which they’re defined. Next, you’ll need to create a vector by declaring a variable and indicating the data type of your desired elements. For example:

std::vector<int> number;

where std is an abbreviation for the STL, “int” is the type of vector (namely, integer), and “number” is the name of the vector.

vector in C++ stl
Assigning a value to the “int” variable.

©History-Computer.com

After this, you need to initialize the vector, meaning you must assign a value to the “int” variable as a starting point. Generally, this can be done in two ways, directly or indirectly, by providing these values to the vector. To directly provide the values, we use the following code:

#include <vector>
#include <iostream>

int main() {
    std::vector<int> vectora {2, 4, 6, 8, 10};
    
    for (int i : vectora) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

This will produce a vector with 2, 4, 6, 8, and 10 as its elements, and print the output to the console. To indirectly initialize, you can simply declare the size and value of the vector, as follows:

vector<int> vectorb(10, 2);

This will produce a vector of size 10, with each element being equal to 2. These results are shown in the screenshots above.

How Can Vectors in C++ STL Be Used?

There are many ways to use vectors in C++ STL, depending on your goals. We’ll go through some of the most common ways, with examples.

Iterators

vector in C++ stl
Iterating over the vector “vec.”

©History-Computer.com

These are object types used to traverse elements within the vector. Much like pointers, iterators can be incremented and decremented, as well as used to obtain the value of the element pointed to. The types of iterators are:

  • begin(): This returns an iterator that points to the first vector element.
  • end(): The returned iterator here points to the element that would theoretically follow the last vector element.
  • rbegin(): Instead of the first, the returned iterator points to the last element, i.e. a reversed beginning.
  • rend(): The iterator here points to the theoretical element preceding the first element.
  • cbegin() and cend(): Similar to begin() and end(), except the iterator is constant, meaning it cannot modify the value it’s pointing to.
  • crbegin() and crend(): Similar to rbegin() and rend(), but with a constant iterator.

The following code illustrates every kind of iterator that can be used with vectors.

#include <iostream>
#include <vector>

int main() {
    // Create a vector of integers
    std::vector<int> vec{1, 2, 3, 4, 5};

    // 1. Using a regular for loop with an index variable
    for (std::size_t i = 0; i < vec.size(); i++) {
        std::cout << vec[i] << " ";
    }
    std::cout << std::endl;

    // 2. Using an iterator
    for (auto it = vec.begin(); it != vec.end(); it++) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 3. Using a const_iterator (to iterate over a const vector)
    const std::vector<int> const_vec{6, 7, 8, 9, 10};
    for (auto it = const_vec.cbegin(); it != const_vec.cend(); it++) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 4. Using a reverse_iterator (to iterate in reverse order)
    for (auto it = vec.rbegin(); it != vec.rend(); it++) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 5. Using a const_reverse_iterator (to iterate over a const vector in reverse order)
    for (auto it = const_vec.crbegin(); it != const_vec.crend(); it++) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    return 0;
}

Code Explanation

Here, we’re using for loops to iterate over the vector “vec.” For the constant iterators, we create a second vector called “const_vec.”

Capacity Functions

vector in C++ stl
Initializing the vector “vec.”

©History-Computer.com

The amount of functions that can be used with vectors is vast, but functions to do with assessing and changing the size of the vector are very common. Functions concerning capacity are described as follows:

  • size(): This returns the size of the vector, i.e. the number of elements.
  • max_size(): This returns the maximum number of elements the vector can hold.
  • resize(n): Resizes the vector so that it contains “n” number of elements.
  • capacity(): This returns the number of elements the vector can currently hold without increasing its memory allocation.
  • empty(): Checks whether the vector is empty or not.
  • shrink_to_fit(): This decreases the capacity of the vector to fit only its current elements.
  • reserve(): This “reserves” space in the vector for a given number of elements.

As before, we’ve demonstrated how to use these functions with an example, which is shown next.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec;

    std::cout << "Initial size of vec: " << vec.size() << std::endl;
    std::cout << "Max size of vec: " << vec.max_size() << std::endl;

    vec.reserve(10);
    std::cout << "Capacity of vec after reserving 10 elements: " << vec.capacity() << std::endl;

    for (int i = 0; i < 5; i++) {
        vec.push_back(i);
    }
    std::cout << "Size of vec after adding 5 elements: " << vec.size() << std::endl;

    vec.resize(10);
    std::cout << "Size of vec after resizing to 10 elements: " << vec.size() << std::endl;

    if (vec.empty()) {
        std::cout << "Vector is empty." << std::endl;
    } else {
        std::cout << "Vector is not empty." << std::endl;
    }

    vec.shrink_to_fit();
    std::cout << "Capacity of vec after shrinking to fit its size: " << vec.capacity() << std::endl;

    return 0;
}

Code Explanation

First, we initialized the vector “vec”, and then printed the initial and max size. Next, space for 10 elements is reserved, and then 5 elements are added. After this, the vector is resized to a size of 10 elements, the vector is checked for emptiness, and then shrunk to fit. The results at every stage are printed, as shown in the image.

Accessing Elements

vector in C++ stl
Creating the vector “vec” and initializing it with 5 elements.

©History-Computer.com

Having access to the elements in your vector is almost as important as modifying the contents. The functions that are used to access elements are:

  • operator(): This accesses the element at the specified vector index.
  • at(): This also accesses the element at a specified index, except it give. an “std::out_of_range” exception if the index is out of range.
  • front(): This returns a reference to the first vector element.
  • back(): As with front, but with the last vector element.
  • data(): This returns the first element’s pointer.

We can illustrate these functions with the code below.

#include <iostream>
#include <vector>

int main() {
  std::vector<int> vec = {1, 2, 3, 4, 5};

  std::cout << "Element at index 2: " << vec[2] << std::endl;

  try {
    std::cout << "Element at index 6: " << vec.at(6) << std::endl;
  } catch (const std::out_of_range& e) {
    std::cerr << "Out of range exception: " << e.what() << std::endl;
  }

  std::cout << "First element: " << vec.front() << std::endl;

  std::cout << "Last element: " << vec.back() << std::endl;

  int* ptr = vec.data();
  std::cout << "Elements in vector: ";
  for (std::size_t i = 0; i < vec.size(); ++i) {
    std::cout << *(ptr + i) << " ";
  }
  std::cout << std::endl;

  return 0;
}

Code Explanation

To start, we create the vector “vec” and initialize it with 5 elements. The second element is accessed using operator(). The at() function then attempts to access the 6th element, but this doesn’t exist, so an error message is produced using the try-catch block.

The first and last elements are then accessed with front() and back(), respectively, and then the data() function points to each element incrementally, and all the results are printed. You can see the output in the screenshot.

Modifying Elements

vector in C++ stl
Using assign() to replace values {1, 2, 3} with values {4, 5, 6}.

©History-Computer.com

Now we’ve covered how to access your vector elements, assess the vector capacity and traverse the vector, it’s time to show how to modify the contents. The functions used to modify the elements are as follows:

  • assign(): This assigns a new value to vector elements, replacing the old values.
  • push_back(): This “pushes” the elements in question into the back of the vector.
  • pop_back(): Instead of adding elements to the back, this removes elements from the back.
  • insert(): New elements are added before the specified element.
  • erase(): The elements at the specified position are removed.
  • clear(): All elements of the vector are removed.
  • swap(): The contents of each specified vector are swapped with one another.
  • emplace(): The vector is extended by creating an element at the specified position, rather than simply copying the value in.
  • emback(): Similar to emplace(), except the element is added to the back of the vector.

To illustrate these functions, consider the following code:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec {1, 2, 3};

    vec.assign({4, 5, 6});

    vec.push_back(7);

    vec.pop_back();

    vec.insert(vec.begin() + 1, 8);

    vec.erase(vec.begin() + 1);

    std::vector<int> vec2 {10, 20, 30};

    vec.swap(vec2);

    vec.clear();

    vec.emplace(vec.begin(), 9);

    vec.emplace_back(11);

    std::cout << "vec: ";
    for (int i : vec) {
        std::cout << i << " ";
    }
    std::cout << "\nvec2: ";
    for (int i : vec2) {
        std::cout << i << " ";
    }
    std::cout << std::endl;

    return 0;
}

Code Explanation

We begin by creating the vector “vec”, with values {1, 2, 3.} Assign() is then used to replace these values with {4, 5, 6.} The element 7 is then pushed to the back of the vector, giving {4, 5, 6, 7.}

7 is then removed from the vector, and the element 8 is inserted before the second vector element, giving values {4, 8, 5, 6.} The second element is then erased, which was the element we just added.

We then create “vec2”, and the contents of both vectors are swapped, so that “vec” is equal to {10, 20, 30} and “vec2” is equal to {4, 5, 6.} All of the elements are now removed from “vec”, an element of 9 is inserted into “vec” at the first position and an element of 11 is inserted into the end of “vec.”

All of this gives “vec” as {9, 11} and “vec2” as {10, 20, 30},” as seen in the screenshot above.

What Are the Time and Space Complexities of Using Vectors?

This does depend on the functions being used, but, generally, most operations have a time complexity of O(1). This is because accessing, inserting, or removing elements doesn’t depend on the vector size, so long as elements aren’t being added at the end and the array isn’t resized.

When modifying elements in the middle, the time complexity is often O(n), as this depends on shifting the other elements. The space complexity is equal to O(n), as it’s proportional to the size of the vector.

Vectors In C++ STL: Wrapping Up

Overall, vectors are a key component of the C++ STL, and they’re largely used for their dynamic resizing capabilities. Accessing elements uses constant time, and many functions can be used efficiently with vectors. While they can be memory intensive because of their resizing ability, vectors are a flexible data structure that all C++ programmers should be aware of.

Frequently Asked Questions

What is a vector in C++ STL?

A vector is a type of dynamic array, meaning that it can be automatically resized during execution to incorporate changing elements. Vectors allow for many functions to be used, and are overall a flexible data structure enabling easy adjustment of elements.

 

How are vectors created?

Vectors can be created by specifying the data type and name, e.g. “std::vector<type> name;.”

Do I need to specify the vector size at creation?

No, you can create a vector without specifying its size straight away. You can either initialize the vector with some list of elements, or add elements as you require them.

What functions can be used with vectors?

There’s a plethora of functions that can be used with vectors, but the most common are the iterator functions (i.e. begin(), end(), crbegin(), crend()), capacity functions (i.e. size(), max_size(), empty(), reserve()), access functions (i.e. operator(), at(), front(), back()) and modifier functions (i.e. push_back(), pop_back(), emplace(), clear()).

What is the time complexity of vector operations?

Generally, the time complexity is O(1) for accessing and modifying elements at the last position of the vector, and O(n) for modifying elements in the middle.

What is the space complexity of vector operations?

The space complexity is equal to O(n) generally, or proportional to the vector size. But this does depend on the number of elements and the amount of reserved memory.

What advantages do vectors have over traditional arrays?

Vectors are dynamic, so they can resize their contents as needed. This tends to be more efficient than adjusting the elements within a traditional array. Vectors also allocate memory automatically and tend to be easier to use.

Can vectors be used as parameters?

Yes, you can use vectors as parameters to functions. To do this, you need to pass the vector to the function, either by reference or by value.

Can vectors store different object types?

No, vectors can only be used to directly store objects that share a type. You can, however, create a class with multiple object types and then create vectors associated with these.

Can vectors be used with user-defined types?

Yes, you can use vectors with user-defined types of data. You just need to declare the vector within the defined data type. Since vectors are dynamic, you can add and remove objects from the data type as necessary.

To top