Skip to content

📝 Knowledge Test

/
Knowledge Test Score Board
—· 0%

Work through the questions below — your score updates as you go.

Keep going · grade bands mapped to DCU's honours scale

target15:00

Only your first attempt at each question counts toward this score. Reload the page to reset.

This section contains 20 interactive knowledge checks designed to test your understanding of the materials covered in Chapter 6. The questions cover generic programming with templates, the Standard Template Library (STL), robust memory management using smart pointers, and modern C++ features like move semantics, lambdas, and std::optional.

Please remember that many of the quizzes have multiple correct answers, and you must select all applicable options to succeed. I have carefully balanced the lengths of the answers, so take your time to evaluate each option thoroughly.

Good luck!

Derek.


Q1
Code Cloze
C++

Defining a Function Template

Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.

1// A generic function to add two values together
2template <····· T>
3T add(····· a, ····· b) {
4 return a + b;
5}

Available Snippets

type
Template
auto
class
typename
T
T
Q2
Quiz
Select 0/1

Why is it common practice to place complete C++ template definitions directly within header files, rather than splitting them into separate source files?

Because the compiler must have access to the full template definition to generate type-specific code upon instantiation.
Because placing them in header files allows the compiler to automatically deduce the required C++20 Concepts.
Because the linker automatically rejects template instantiations that span multiple translation units to avoid memory fragmentation.
Because templates bypass the standard compilation phase and are interpreted dynamically at program execution time.
Q3
Concept Match

Match the Template Terminology

Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.

Full Specialisation
drag a definition here…
Partial Specialisation
drag a definition here…
Concepts (C++20)
drag a definition here…
Generic Template
drag a definition here…

Definition Pool

Explicitly specifying requirements on template parameters to ensure proper usage and clearer compile-time errors.
Customising a class template for a subset or category of types, such as all pointer types.
The primary template definition that serves as a fallback for types that do not match any specialisation.
Providing a completely customised implementation of a template for one specific concrete type (e.g., bool).
Q4
Code Output
C++

Predict the output: Templates and Static Members

Read the code below, then choose the terminal output it produces and click Submit.

1#include <iostream>
2
3template<typename T>
4class Config {
5public:
6 static int loadCount;
7 Config() { loadCount++; }
8};
9
10// Initialise static member
11template<typename T>
12int Config<T>::loadCount = 0;
13
14int main() {
15 Config<int> a;
16 Config<int> b;
17 Config<float> c;
18
19 std::cout << Config<int>::loadCount << " " << Config<float>::loadCount;
20 return 0;
21}
stdout
3 3
stdout
2 1
stdout
3 0
stdout
1 1
Q5
Quiz
Select 0/2

Which of the following statements accurately describe the benefits of C++20 Concepts?

They provide explicit requirements on template parameters, leading to clearer code and more readable compiler errors.
They force class templates to be allocated strictly on the stack, preventing dynamic memory fragmentation.
They allow developers to constrain a template so it only accepts specific types, like integral or floating-point numbers.
They completely eliminate the need for template specialisation by dynamically adjusting data types during program execution.

Part 2: The Standard Template Library (STL)

Section titled “Part 2: The Standard Template Library (STL)”
Q6
Concept Match

Match the STL Container to its Description

Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.

std::vector
drag a definition here…
std::list
drag a definition here…
std::map
drag a definition here…
std::span
drag a definition here…

Definition Pool

A doubly linked list ideal for frequent insertions and removals at any position.
A collection of sorted key-value pairs where keys must be strictly unique.
A dynamic array providing fast random access and contiguous memory allocation.
A non-owning view over a contiguous sequence, avoiding unnecessary copies (C++20).
Q7
Code Cloze
C++

Using C++20 Ranges for Sorting

Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.

1#include <vector>
2#include <·····> // the header that declares std::ranges::sort
3
4int main() {
5 std::vector<int> data = {5, 2, 8, 1, 9};
6
7 // Modern C++20 approach to sorting
8 std::·····::·····(data);
9}

Available Snippets

std
ranges
iterator
begin
numeric
sort
algorithm
Q8
Quiz
Select 0/2

Which of the following statements correctly contrast Iterator categories in the C++ STL?

A forward iterator can only be dereferenced once per position, whereas an input iterator allows multiple passes over the same data.
Standard vectors and arrays provide random access iterators, whereas standard lists only provide bidirectional iterators.
A bidirectional iterator cannot be used to modify elements, whereas a random access iterator is strictly read/write only.
A bidirectional iterator moves one step at a time (forward or backward), whereas a random access iterator can jump directly to any index in constant time.
Q9
Quiz
Select 0/1

In the context of the STL, what exactly is a 'functor' (function object)?

A class or struct that has overloaded the 'operator()' to allow instantiated objects to be called like a standard function.
A keyword used to declare that a particular algorithm has exclusive access to a container's private data.
A specialized smart pointer that automatically manages the memory of lambda expressions on the heap.
An internal compiler mechanism used to enforce C++20 Concepts across multiple translation units.
Q10
Code Output
C++

Predict the output: std::for_each with a Lambda

Read the code below, then choose the terminal output it produces and click Submit.

1#include <iostream>
2#include <vector>
3#include <algorithm>
4
5int main() {
6 std::vector<int> v = {2, 4, 6};
7 int total = 0;
8
9 std::for_each(v.begin(), v.end(), [&total](int x) {
10 total += x * 2;
11 });
12
13 std::cout << total;
14 return 0;
15}
stdout
12
stdout
24
stdout
0
stdout
6

Part 3: Smart Pointers and Memory Management

Section titled “Part 3: Smart Pointers and Memory Management”
Q11
Concept Match

Match the Smart Pointer Concept

Drag each definition into its matching concept slot, then click Submit. Tap × to return a placed card to the pool.

std::unique_ptr
drag a definition here…
std::shared_ptr
drag a definition here…
std::weak_ptr
drag a definition here…
Control Block
drag a definition here…

Definition Pool

A small heap allocation that stores the strong count, weak count, and custom deleter.
Observes a shared object without increasing its strong reference count; used to break cycles.
Enforces strict single ownership; is exactly 8 bytes on the stack and non-copyable.
Allows multiple owners via reference counting; requires 16 bytes on the stack.
Q12
Quiz
Select 0/1

Why is using 'std::make_shared' generally preferred over directly constructing a shared pointer with 'std::shared_ptr<T>(new T)'?

Because std::make_shared is guaranteed to be completely immune to throwing exceptions during memory allocation.
Because std::shared_ptr(new T) is deprecated in C++11 and has been entirely removed from the C++20 standard.
Because std::make_shared forces the resulting pointer to be non-copyable, actively preventing circular references.
Because std::make_shared performs a single 'fused' heap allocation for both the object and the control block, improving cache locality.
Q13
Code Cloze
C++

Safely Accessing a Weak Pointer

Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.

1#include <iostream>
2#include <memory>
3
4class Sensor {
5public:
6 int getValue() const { return 42; }
7};
8
9void checkSensor(std::weak_ptr<Sensor> weakSensor) {
10 // Attempt to promote the weak_ptr to a shared_ptr
11 if (auto temp = weakSensor.·····()) {
12 std::cout << "Sensor is alive. Value: " << temp->·····() << std::endl;
13 } else {
14 std::cout << "Sensor has been destroyed." << std::endl;
15 }
16}

Available Snippets

acquire
lock
->
get
getValue
value
Q14
Quiz
Select 0/2

Which of the following statements are TRUE regarding custom deleters and smart pointers?

You must explicitly call 'delete' (or equivalent cleanup) within the custom deleter to prevent memory leaks.
You cannot use std::make_shared or std::make_unique when a custom deleter is required.
Custom deleters are only permitted for managing file handles, not dynamically allocated heap memory.
Custom deleters automatically disable the smart pointer's internal reference counting mechanism.
Q15
Code Cloze
C++

Transferring Ownership of a Unique Pointer

Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.

1#include <memory>
2
3int main() {
4 // Create the unique pointer safely
5 auto s1 = std::·····<Sensor>(101);
6
7 // Transfer ownership to s2; s1 becomes empty
8 std::unique_ptr<Sensor> s2 = std::·····(·····);
9
10 return 0;
11}

Available Snippets

transfer
make_shared
make_unique
copy
s2
move
s1
Q16
Code Cloze
C++

Implementing a Move Constructor

Drag snippets from the pool into the blanks so the program produces the output shown, then click Submit.

1class Buffer {
2 int* data;
3public:
4 // Move Constructor takes an rvalue reference
5 Buffer(Buffer····· source) ····· {
6 data = source.data; // Steal the pointer
7 source.data = ·····; // Prevent double deletion
8 }
9};

Available Snippets

&&
NULL
move
noexcept
nullptr
const
&
Q17
Quiz
Select 0/2

What are the primary performance and safety benefits of using Move Semantics over traditional deep copying?

It allows containers like std::vector to resize efficiently by transferring resource ownership rather than duplicating data.
It prevents the expensive overhead of allocating new heap memory when returning large objects from functions.
It entirely eliminates the need for constructors and destructors to be executed during the object lifecycle.
It guarantees that source objects are permanently locked in read-only memory after their resources are moved.
Q18
Quiz
Select 0/1

In a C++ lambda expression, what does the capture list '[=]' signify?

It restricts the lambda function, preventing it from accessing any external variables from the surrounding scope.
It captures all variables used inside the lambda from the surrounding scope by value, creating local copies.
It captures all variables used inside the lambda from the surrounding scope by reference.
It automatically assigns default integer values to all uninitialised variables used within the lambda.
Q19
Quiz
Select 0/1

Why is it considered dangerous (and undefined behaviour) to return a std::string_view that refers to a local std::string variable?

Because the local std::string is destroyed when the function returns, leaving the string_view pointing at freed memory.
Because string_view objects are always heap-allocated, so they cannot safely reference stack-based strings.
Because the compiler strictly enforces that string_view objects must outlive their source strings at compile time.
Because std::string_view only supports read-only access and cannot copy the string data before destruction.
Q20
Quiz
Select 0/2

Why is std::optional (C++17) generally considered a robust, 'zero-overhead' error handling choice for Edge Programming?

Because it guarantees that operations will always succeed, completely eliminating the need for the CPU to perform error-checking.
Because the wrapped value is stored inline directly within the optional object on the stack, requiring no dynamic heap allocation.
Because it explicitly models the absence of a value in the type system, replacing error-prone sentinel values like -1 or nullptr.
Because the compiler automatically offloads the optional validation logic to a dedicated hardware coprocessor during runtime.

Congratulations on completing the Chapter 6 Knowledge Test! Review any questions you missed to ensure a solid grasp of Templates, the STL, and Smart Pointers before moving forward.