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

auto
type
class
T
Template
T
typename
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 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.
Because placing them in header files allows the compiler to automatically deduce the required C++20 Concepts.
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.
The primary template definition that serves as a fallback for types that do not match any specialisation.
Customising a class template for a subset or category of types, such as all pointer types.
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 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.
They force class templates to be allocated strictly on the stack, preventing dynamic memory fragmentation.
They provide explicit requirements on template parameters, leading to clearer code and more readable compiler errors.

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 dynamic array providing fast random access and contiguous memory allocation.
A non-owning view over a contiguous sequence, avoiding unnecessary copies (C++20).
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.
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
begin
sort
std
ranges
ranges
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 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.
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.
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.
A small heap allocation that stores the strong count, weak count, and custom deleter.
Allows multiple owners via reference counting; requires 16 bytes on the stack.
Enforces strict single ownership; is exactly 8 bytes on the stack and non-copyable.
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::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 is guaranteed to be completely immune to throwing exceptions during memory allocation.
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
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

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

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

Custom deleters automatically disable the smart pointer's internal reference counting mechanism.
Custom deleters are only permitted for managing file handles, not dynamically allocated heap memory.
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.
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

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

move
NULL
&&
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 guarantees that source objects are permanently locked in read-only memory after their resources are moved.
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.
Q18
Quiz
Select 0/1

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

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 captures all variables used inside the lambda from the surrounding scope by reference.
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 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 explicitly models the absence of a value in the type system, replacing error-prone sentinel values like -1 or nullptr.
Because the wrapped value is stored inline directly within the optional object on the stack, requiring no dynamic heap allocation.
Because it guarantees that operations will always succeed, completely eliminating the need for the CPU to perform error-checking.
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.