C++ The Standard Template Library (STL) Quiz

C++
0 Passed
0% acceptance

40 in-depth questions covering C++ STL fundamentals including std::vector, std::map, std::unordered_map, std::pair, std::tuple, std::set, and best practices for containers — with 16 code examples to master STL usage and pitfalls.

40 Questions
~80 minutes
1

Question 1

What is the primary purpose of the C++ Standard Template Library (STL)?

A
To provide generic, reusable containers and algorithms that work with any data type through templates, enabling efficient and type-safe data structures and operations
B
To replace all user-defined classes with standard implementations
C
To provide low-level memory management functions
D
To implement object-oriented programming features
2

Question 2

What is the main difference between std::vector and std::array?

A
std::vector provides dynamic sizing with automatic memory management, while std::array has fixed compile-time size with stack allocation
B
std::array is faster than std::vector for all operations
C
std::vector cannot store primitive types while std::array can
D
They are identical in functionality and performance
3

Question 3

What is the difference between std::map and std::unordered_map?

cpp
#include <map>
#include <unordered_map>
#include <iostream>

int main() {
    std::map<int, std::string> ordered;
    std::unordered_map<int, std::string> unordered;
    
    ordered[3] = "three";
    ordered[1] = "one";
    ordered[2] = "two";
    
    unordered[3] = "three";
    unordered[1] = "one";
    unordered[2] = "two";
    
    std::cout << "Map (ordered): ";
    for (const auto& p : ordered) std::cout << p.first << " ";
    
    std::cout << "\nUnordered map: ";
    for (const auto& p : unordered) std::cout << p.first << " ";
    
    return 0;
}
A
std::map maintains sorted order with O(log n) operations using red-black trees, while std::unordered_map provides average O(1) operations using hash tables but without ordering guarantees
B
std::unordered_map is always faster than std::map for all operations
C
std::map uses hash tables while std::unordered_map uses trees
D
They have identical performance and ordering characteristics
4

Question 4

What is the purpose of std::pair and when should it be used?

A
To group two heterogeneous values together, commonly used with std::map elements and functions returning multiple values
B
To create arrays of pairs for mathematical operations
C
To replace all struct definitions in C++ code
D
To implement complex data structures like trees and graphs
5

Question 5

What is std::tuple and how does it differ from std::pair?

cpp
#include <tuple>
#include <iostream>

int main() {
    std::pair<int, std::string> p = {42, "hello"};
    std::tuple<int, std::string, double> t = {42, "hello", 3.14};
    
    std::cout << std::get<0>(t) << " " 
              << std::get<1>(t) << " " 
              << std::get<2>(t) << std::endl;
    
    return 0;
}
A
std::tuple can hold any number of heterogeneous elements (not limited to two), accessed via std::get<N> or structured bindings
B
std::tuple is faster than std::pair for all operations
C
std::pair can hold more elements than std::tuple
D
They are identical in functionality
6

Question 6

What is the difference between std::set and std::unordered_set?

A
std::set maintains sorted unique elements with logarithmic operations, while std::unordered_set provides average constant-time operations with hash-based storage
B
std::unordered_set maintains sorted order while std::set does not
C
std::set allows duplicate elements while std::unordered_set does not
D
They have identical performance characteristics
7

Question 7

What is vector capacity and why does it matter for performance?

cpp
#include <vector>
#include <iostream>

int main() {
    std::vector<int> vec;
    
    std::cout << "Size: " << vec.size() 
              << ", Capacity: " << vec.capacity() << std::endl;
    
    for(int i = 0; i < 100; ++i) {
        vec.push_back(i);
        if (i % 20 == 0) {
            std::cout << "Size: " << vec.size() 
                      << ", Capacity: " << vec.capacity() << std::endl;
        }
    }
    
    return 0;
}
A
Capacity is the allocated memory size, separate from size (element count), and pre-reserving capacity prevents reallocations during growth for better performance
B
Capacity and size are always equal in std::vector
C
Capacity only affects memory usage, not performance
D
Capacity determines the maximum number of elements that can be stored
8

Question 8

What is the difference between std::vector::push_back and std::vector::emplace_back?

cpp
#include <vector>
#include <string>
#include <iostream>

class Item {
public:
    std::string name;
    int value;
    Item(std::string n, int v) : name(n), value(v) {
        std::cout << "Constructor called\n";
    }
};

int main() {
    std::vector<Item> vec;
    
    // push_back creates temporary then moves/copies
    vec.push_back(Item("temp", 42));
    
    // emplace_back constructs in-place
    vec.emplace_back("direct", 24);
    
    return 0;
}
A
emplace_back constructs the element in-place using the provided arguments, avoiding temporary object creation, while push_back requires a constructed object
B
They are identical in functionality and performance
C
push_back is faster for primitive types, emplace_back for complex objects
D
emplace_back can only be used with default-constructible types
9

Question 9

What is iterator invalidation and why is it important in STL containers?

A
Iterator invalidation occurs when container operations make existing iterators unsafe to use, requiring careful iterator management to prevent undefined behavior
B
Iterator invalidation only happens with vector resize operations
C
Iterator invalidation is impossible in modern STL implementations
D
Iterator invalidation only affects const iterators
10

Question 10

What is the difference between std::map::operator[] and std::map::at()?

cpp
#include <map>
#include <iostream>

int main() {
    std::map<std::string, int> scores;
    
    try {
        // at() throws exception for non-existent key
        int value = scores.at("nonexistent");
    } catch (const std::out_of_range& e) {
        std::cout << "Exception caught\n";
    }
    
    // operator[] creates default value for non-existent key
    int defaulted = scores["newkey"];  // Creates scores["newkey"] = 0
    
    return 0;
}
A
operator[] creates a default value for non-existent keys, while at() throws std::out_of_range exception for bounds-checked access
B
at() is faster than operator[] for all operations
C
operator[] throws exceptions while at() creates default values
D
They are identical in behavior and performance
11

Question 11

What is structured binding and how does it work with STL containers?

cpp
#include <map>
#include <tuple>
#include <iostream>

int main() {
    std::map<std::string, int> scores = {{"Alice", 95}, {"Bob", 87}};
    
    // Structured binding with map
    for (const auto& [name, score] : scores) {
        std::cout << name << ": " << score << std::endl;
    }
    
    // Structured binding with tuple
    std::tuple<int, std::string, double> data = {42, "hello", 3.14};
    auto [id, text, value] = data;
    
    return 0;
}
A
Structured binding unpacks tuple-like objects into individual variables, enabling clean syntax for pairs, tuples, and structured data access
B
Structured binding only works with arrays and cannot be used with STL containers
C
Structured binding is slower than traditional access methods
D
Structured binding requires C++20 and cannot be used in earlier versions
12

Question 12

What is the difference between std::vector::reserve and std::vector::resize?

cpp
#include <vector>
#include <iostream>

int main() {
    std::vector<int> vec;
    
    vec.reserve(10);  // Allocates space for 10 elements
    std::cout << "After reserve: size=" << vec.size() 
              << ", capacity=" << vec.capacity() << std::endl;
    
    vec.resize(5);    // Changes size to 5, default-initializes elements
    std::cout << "After resize: size=" << vec.size() 
              << ", capacity=" << vec.capacity() << std::endl;
    
    return 0;
}
A
reserve() allocates memory without changing size, while resize() changes the logical size and may allocate memory if needed
B
They are identical in functionality
C
resize() only affects capacity, reserve() affects size
D
reserve() can shrink capacity while resize() cannot
13

Question 13

What is the purpose of std::make_pair and std::make_tuple?

A
They provide template argument deduction for pair/tuple construction, avoiding explicit template parameters in complex type expressions
B
They create pairs and tuples with dynamic memory allocation
C
They are required for all pair and tuple operations
D
They provide thread-safe pair and tuple construction
14

Question 14

What is the difference between std::set::insert and std::set::emplace?

cpp
#include <set>
#include <string>
#include <iostream>

class Item {
public:
    std::string name;
    Item(std::string n) : name(n) {
        std::cout << "Constructor: " << name << std::endl;
    }
};

int main() {
    std::set<Item> items;
    
    // insert requires constructed object
    Item temp("temp");
    items.insert(temp);
    
    // emplace constructs in-place
    items.emplace("direct");
    
    return 0;
}
A
emplace constructs the element in-place using provided arguments, while insert requires a fully constructed object that may be copied or moved
B
They are identical for all set operations
C
insert is faster for complex objects, emplace for simple types
D
emplace can only be used with default-constructible types
15

Question 15

What is the difference between std::map::find and std::map::count?

A
find() returns an iterator to the element (or end() if not found), while count() returns the number of elements with that key (0 or 1 for map)
B
count() is faster than find() for existence checking
C
find() can only be used with ordered maps, count() with unordered maps
D
They provide identical functionality with different return types
16

Question 16

What is the difference between std::vector::begin() and std::vector::cbegin()?

A
begin() returns a read-write iterator, cbegin() returns a read-only const_iterator for safe access to const vectors
B
cbegin() is faster than begin() for all operations
C
begin() can only be used with non-const vectors
D
They are identical in functionality
17

Question 17

What is the purpose of std::tie and how does it relate to structured bindings?

cpp
#include <tuple>
#include <iostream>

int main() {
    std::tuple<int, std::string, double> data = {42, "hello", 3.14};
    
    // Using tie (pre-C++17)
    int id;
    std::string text;
    double value;
    std::tie(id, text, value) = data;
    
    // Using structured bindings (C++17+)
    auto [new_id, new_text, new_value] = data;
    
    return 0;
}
A
std::tie unpacks tuple elements into existing variables, while structured bindings create new variables - both enable tuple decomposition
B
std::tie is faster than structured bindings for all operations
C
Structured bindings replace std::tie completely in modern C++
D
std::tie can only be used with pairs, not tuples
18

Question 18

What is the difference between std::vector::erase and std::vector::clear?

A
erase() removes specific elements or ranges, while clear() removes all elements from the container
B
clear() only removes elements, erase() also deallocates memory
C
erase() can only remove single elements, clear() removes ranges
D
They are identical in functionality
19

Question 19

What is the difference between std::set and std::multiset?

A
std::set stores unique elements, std::multiset allows duplicate elements while maintaining sorted order
B
std::multiset is unordered while std::set maintains order
C
std::set allows duplicates, std::multiset does not
D
They have identical behavior and performance
20

Question 20

What is the difference between std::map::lower_bound and std::map::upper_bound?

cpp
#include <map>
#include <iostream>

int main() {
    std::map<int, std::string> data = {{1, "one"}, {3, "three"}, {5, "five"}};
    
    // lower_bound finds first element >= key
    auto lb = data.lower_bound(3);
    std::cout << "lower_bound(3): " << lb->first << std::endl;
    
    // upper_bound finds first element > key
    auto ub = data.upper_bound(3);
    std::cout << "upper_bound(3): " << ub->first << std::endl;
    
    return 0;
}
A
lower_bound returns iterator to first element >= key, upper_bound returns iterator to first element > key, used together for range queries
B
They are identical in functionality
C
upper_bound is faster than lower_bound for all operations
D
lower_bound can only be used with ordered maps
21

Question 21

What is the difference between std::vector::front() and std::vector::at(0)?

A
front() provides unchecked access to the first element, while at(0) provides bounds-checked access that throws std::out_of_range for empty vectors
B
at(0) is faster than front() for all vector operations
C
front() can only be used with non-empty vectors
D
They are identical in behavior and performance
22

Question 22

What is the difference between std::tuple_cat and std::make_tuple?

cpp
#include <tuple>
#include <iostream>

int main() {
    std::tuple<int, std::string> t1 = {1, "hello"};
    std::tuple<double, char> t2 = {3.14, 'x'};
    
    // make_tuple creates new tuple
    auto t3 = std::make_tuple(42, "world");
    
    // tuple_cat concatenates existing tuples
    auto t4 = std::tuple_cat(t1, t2);
    
    std::cout << std::get<0>(t4) << " " 
              << std::get<1>(t4) << " " 
              << std::get<2>(t4) << " " 
              << std::get<3>(t4) << std::endl;
    
    return 0;
}
A
std::make_tuple creates a new tuple from values, std::tuple_cat concatenates multiple existing tuples into a single larger tuple
B
They are identical in functionality
C
tuple_cat is faster than make_tuple for all operations
D
make_tuple can concatenate tuples, tuple_cat cannot
23

Question 23

What is the difference between std::vector::shrink_to_fit and std::vector::clear?

A
shrink_to_fit reduces capacity to match current size (potentially moving elements), while clear removes all elements but keeps capacity
B
They are identical in functionality
C
clear() can reduce capacity, shrink_to_fit() cannot
D
shrink_to_fit() removes elements, clear() affects capacity
24

Question 24

What is the difference between std::set::equal_range and std::set::find?

A
equal_range returns a pair of iterators representing all elements equal to the key, while find returns a single iterator to one matching element
B
equal_range is faster than find for all operations
C
find can return multiple elements, equal_range returns only one
D
They are identical for set containers
25

Question 25

What is the difference between std::map::emplace and std::map::insert?

cpp
#include <map>
#include <string>
#include <iostream>

class Item {
public:
    std::string name;
    int value;
    Item(std::string n, int v) : name(n), value(v) {
        std::cout << "Constructor called\n";
    }
};

int main() {
    std::map<std::string, Item> items;
    
    // insert requires constructed object
    Item temp("temp", 42);
    items.insert({"key1", temp});
    
    // emplace constructs in-place
    items.emplace("key2", "direct", 24);
    
    return 0;
}
A
emplace constructs the value in-place using provided arguments, avoiding temporary object creation, while insert requires a fully constructed value object
B
They are identical for all map operations
C
insert is faster for complex objects, emplace for simple types
D
emplace can only be used with default-constructible value types
26

Question 26

What is the difference between std::vector::data() and std::vector::begin()?

A
data() returns a raw pointer to the underlying array, while begin() returns an iterator that can be used with STL algorithms
B
They are identical in functionality
C
begin() is faster than data() for all operations
D
data() can only be used with empty vectors
27

Question 27

What is the difference between std::pair::first and std::pair::second?

A
first accesses the first element of the pair, second accesses the second element - they provide direct member access to pair components
B
They are identical in functionality
C
first is faster than second for all operations
D
second can only be used with certain pair types
28

Question 28

What is the difference between std::tuple_size and std::tuple_element?

A
tuple_size provides the number of elements in a tuple type, tuple_element provides the type of an element at a specific index
B
They are identical in functionality
C
tuple_element is faster than tuple_size for all operations
D
tuple_size can only be used at runtime
29

Question 29

What is the difference between std::vector::max_size and std::vector::capacity?

A
max_size returns the theoretical maximum number of elements the vector can hold, capacity returns the currently allocated space
B
They are identical in functionality
C
capacity is always larger than max_size
D
max_size changes with each push_back operation
30

Question 30

What is the difference between std::set::key_comp and std::set::value_comp?

A
key_comp compares keys, value_comp compares values (which are the same for set since keys are values)
B
They are identical in functionality
C
value_comp is faster than key_comp for all operations
D
key_comp can only be used with ordered sets
31

Question 31

What is the difference between std::map::key_type and std::map::mapped_type?

A
key_type is the type of the keys, mapped_type is the type of the values associated with those keys
B
They are identical in functionality
C
mapped_type is faster than key_type for all operations
D
key_type can only be used with ordered maps
32

Question 32

What is the difference between std::vector::const_iterator and std::vector::iterator?

A
const_iterator provides read-only access to elements, iterator provides read-write access to elements
B
They are identical in functionality
C
iterator is faster than const_iterator for all operations
D
const_iterator can only be used with empty vectors
33

Question 33

What is the difference between std::tuple::get<I> and std::get<I>?

A
They are identical - both provide compile-time access to tuple elements by index
B
std::tuple::get<I> is faster than std::get<I> for all operations
C
std::get<I> can only be used at runtime
D
std::tuple::get<I> provides bounds checking
34

Question 34

What is the difference between std::set::begin() and std::set::rbegin()?

A
begin() returns iterator to first element, rbegin() returns reverse iterator to last element for backward traversal
B
They are identical in functionality
C
rbegin() is faster than begin() for all operations
D
begin() can only be used with ordered sets
35

Question 35

What is the difference between std::vector::empty() and std::vector::size() == 0?

A
They are functionally identical - empty() is often more readable and potentially optimized for the emptiness check
B
size() == 0 is faster than empty() for all operations
C
empty() can only be used with certain vector types
D
size() == 0 provides more information than empty()
36

Question 36

What is the difference between std::map::cbegin() and std::map::begin()?

A
cbegin() returns a const_iterator for read-only access, begin() returns a regular iterator that may allow modification
B
They are identical in functionality
C
begin() is faster than cbegin() for all operations
D
cbegin() can only be used with empty maps
37

Question 37

What is the difference between std::pair::make_pair and std::make_pair?

A
They are identical - std::make_pair is the global function, std::pair::make_pair would be incorrect syntax
B
std::pair::make_pair is faster than std::make_pair for all operations
C
std::make_pair provides template argument deduction
D
std::pair::make_pair can only be used with default-constructible types
38

Question 38

What is the difference between std::vector::back() and std::vector::at(size()-1)?

A
back() provides unchecked access to the last element, while at(size()-1) provides bounds-checked access that throws for empty vectors
B
They are identical in functionality
C
at(size()-1) is faster than back() for all operations
D
back() can only be used with non-empty vectors
39

Question 39

What is the difference between std::set::cend() and std::set::end()?

A
cend() returns a const_iterator past the last element, end() returns a regular iterator past the last element
B
They are identical in functionality
C
end() is faster than cend() for all operations
D
cend() can only be used with empty sets
40

Question 40

What is the fundamental principle for choosing between STL containers for a given use case?

A
Choose based on access patterns, ordering requirements, and performance needs: vector for sequential access, map for key-value lookup, set for uniqueness, etc.
B
Always use std::vector for everything since it's the most flexible
C
Use std::map for all associative data since it maintains order
D
Container choice has minimal impact on performance and should be based on personal preference

QUIZZES IN C++