Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

📝 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

T
Template
typename
class
type
auto
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 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 the compiler must have access to the full template definition to generate type-specific code upon instantiation.
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

Providing a completely customised implementation of a template for one specific concrete type (e.g., bool).
Customising a class template for a subset or category of types, such as all pointer types.
Explicitly specifying requirements on template parameters to ensure proper usage and clearer compile-time errors.
The primary template definition that serves as a fallback for types that do not match any specialisation.
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 completely eliminate the need for template specialisation by dynamically adjusting data types during program execution.
They allow developers to constrain a template so it only accepts specific types, like integral or floating-point numbers.

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 non-owning view over a contiguous sequence, avoiding unnecessary copies (C++20).
A dynamic array providing fast random access and contiguous memory allocation.
A collection of sorted key-value pairs where keys must be strictly unique.
A doubly linked list ideal for frequent insertions and removals at any position.
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 <algorithm>
3#include <·····>
4
5int main() {
6 std::vector<int> data = {5, 2, 8, 1, 9};
7
8 // Modern C++20 approach to sorting
9 std::·····::·····(data);
10}

Available Snippets

vector
ranges
algorithm
ranges
sort
begin
std
Q8
Quiz
Select 0/2

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

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.
Standard vectors and arrays provide random access iterators, whereas standard lists only provide bidirectional iterators.
A forward iterator can only be dereferenced once per position, whereas an input iterator allows multiple passes over the same data.
Q9
Quiz
Select 0/1

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

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

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.
A small heap allocation that stores the strong count, weak count, and custom deleter.
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 performs a single 'fused' heap allocation for both the object and the control block, improving cache locality.
Because std::make_shared is guaranteed to be completely immune to throwing exceptions during memory allocation.
Because std::make_shared forces the resulting pointer to be non-copyable, actively preventing circular references.
Because std::shared_ptr(new T) is deprecated in C++11 and has been entirely removed from the C++20 standard.
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
4void checkSensor(std::weak_ptr<Sensor> weakSensor) {
5 // Attempt to promote the weak_ptr to a shared_ptr
6 if (auto temp = weakSensor.·····()) {
7 std::cout << "Sensor is alive. Value: " << temp->·····() << std::endl;
8 } else {
9 std::cout << "Sensor has been destroyed." << std::endl;
10 }
11}

Available Snippets

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

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

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

s2
copy
make_shared
make_unique
move
transfer
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

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

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

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 allows containers like std::vector to resize efficiently by transferring resource ownership rather than duplicating data.
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 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.
It captures all variables used inside the lambda from the surrounding scope by value, creating local copies.
It restricts the lambda function, preventing it from accessing any external variables from the surrounding scope.
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 std::string_view only supports read-only access and cannot copy the string data before destruction.
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 the local std::string is destroyed when the function returns, leaving the string_view pointing at freed memory.
Q20
Quiz
Select 0/2

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

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.
Because it guarantees that operations will always succeed, completely eliminating the need for the CPU to perform error-checking.

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.