// STUHUB · C++ DATA STRUCTURES
Data Structures Exam Cheat Sheet (C++ Quick Reference)
Night-before reference for a data structures exam: declarations, complexity tables, the rule that decides each answer, and worked traces in C++.
Introduction
Scannable, not readable. Find a fact, use it, move on. Every code block here was compiled with g++ -std=c++17 -Wall; every printed value is real program output.
The sheet runs in the exam's own order: array, singly linked list, stack, queue (linked and circular), tree and BST, graph, sorting, searching — then three worked traces (infix to postfix, BFT queue state, Dijkstra) and a twelve-item list for the last twenty minutes.
1. Array — declarations
Asked: pointer-arithmetic output, 2D indexing, array length.
int a[5] = {10, 20, 30, 40, 50};
int* p = a; // array name decays to &a[0]
int m[2][3] = {{1,2,3},{4,5,6}};
int len = sizeof(a) / sizeof(a[0]);1. Array — outputs, complexity, and the rule
| Expression | Same as | Output |
|---|---|---|
*(p + 2) | a[2] | 30 |
*(a + 4) | a[4] | 50 |
*(*(m + 1) + 2) | m[1][2] | 6 |
sizeof(a)/sizeof(a[0]) | element count | 5 |
| Operation | Complexity |
|---|---|
| Access by index | O(1) |
| Search (unsorted) | O(n) |
| Insert / delete at position | O(n) (shifting) |
The rule: *(ptr + n) advances by n * sizeof(element), not n bytes. Row-major address: base + (i * COLS + j) * sizeof(element).
Costliest mistake: sizeof(arr)/sizeof(arr[0]) gives the wrong answer inside a function — the parameter is a pointer, so sizeof returns the pointer size. Only valid where the array is declared.
2. Singly linked list — the node
Asked: insert, delete by value, in-place reverse, count nodes.
struct Node {
int data;
Node* next;
Node(int v) : data(v), next(nullptr) {}
};2. Singly linked list — insert, delete, reverse
Insert at the front, delete by value, and reverse in place.
void insertFront(Node*& head, int v) {
Node* n = new Node(v);
n->next = head; // link new node first
head = n; // then move head
}
bool deleteValue(Node*& head, int v) {
if (head == nullptr) return false;
if (head->data == v) { // deleting the head is a separate case
Node* t = head; head = head->next; delete t; return true;
}
Node* prev = head;
while (prev->next != nullptr && prev->next->data != v) prev = prev->next;
if (prev->next == nullptr) return false;
Node* t = prev->next;
prev->next = t->next;
delete t;
return true;
}
void reverseList(Node*& head) {
Node* prev = nullptr;
Node* cur = head;
while (cur != nullptr) {
Node* nxt = cur->next; // 1. save
cur->next = prev; // 2. flip
prev = cur; // 3. advance prev
cur = nxt; // 4. advance cur
}
head = prev; // do not forget this line
}2. Singly linked list — output and cost table
Real output from the compiled demo:
built: 5 -> 10 -> 20 -> 30
del 20: 5 -> 10 -> 30
reversed: 30 -> 10 -> 5
count = 3| Operation | Singly | Doubly | Array |
|---|---|---|---|
| Insert/delete at head | O(1) | O(1) | O(n) |
| Insert at tail (with tail ptr) | O(1) | O(1) | O(1) amortised |
| Delete a given node | O(n) (need prev) | O(1) | O(n) |
| Access k-th element | O(n) | O(n) | O(1) |
| Extra memory per node | 1 pointer | 2 pointers | 0 |
The rule: in reversal, save next before overwriting cur->next. Order is save → flip → advance → advance.
Costliest mistake: forgetting head = prev; at the end of reverse — the list is correctly reversed in memory but head still points at what is now the tail, so printing shows one node.
3. Stack — array implementation
LIFO. Array version, top starts at -1.
| Operation | Complexity |
|---|---|
| push / pop / peek / isEmpty | O(1) |
Precedence (highest first): ^ → * / → + -. ( has lowest precedence once on the stack.
const int MAX = 100;
class ArrayStack {
int arr[MAX];
int top;
public:
ArrayStack() : top(-1) {}
bool isEmpty() const { return top == -1; }
bool isFull() const { return top == MAX - 1; }
void push(int v) { if (isFull()) return; arr[++top] = v; } // pre-increment
int pop() { if (isEmpty()) return -1; return arr[top--]; } // post-decrement
int peek() const{ return isEmpty() ? -1 : arr[top]; }
int size() const{ return top + 1; }
};3. Stack — postfix evaluation
Postfix evaluation:
int evaluatePostfix(const string& exp) {
stack<int> s;
for (char c : exp) {
if (isdigit(c)) {
s.push(c - '0');
} else {
int op2 = s.top(); s.pop(); // RIGHT operand pops first
int op1 = s.top(); s.pop(); // LEFT operand pops second
switch (c) {
case '+': s.push(op1 + op2); break;
case '-': s.push(op1 - op2); break;
case '*': s.push(op1 * op2); break;
case '/': s.push(op1 / op2); break;
}
}
}
return s.top();
}3. Stack — the operand-order trap
Compiled output: evaluatePostfix("62/3-42*+") prints 8 (6/2 = 3, 3−3 = 0, 4×2 = 8, 0+8 = 8).
Costliest mistake: popping the operands in the wrong order. The first value popped is the right operand. Gets - and / wrong every time and + and * right, so it hides until it costs marks.
4a. Queue — linked-list queue
FIFO. Insert at rear, remove from front.
struct QNode { int data; QNode* next; QNode(int v) : data(v), next(nullptr) {} };
class LinkedQueue {
QNode* qFront; QNode* qRear; int count;
public:
LinkedQueue() : qFront(nullptr), qRear(nullptr), count(0) {}
bool isEmpty() const { return qFront == nullptr; }
void enqueue(int v) {
QNode* n = new QNode(v);
if (qRear == nullptr) { qFront = qRear = n; } // first node: both pointers
else { qRear->next = n; qRear = n; }
count++;
}
bool dequeue(int& out) {
if (qFront == nullptr) return false;
QNode* t = qFront;
out = t->data;
qFront = qFront->next;
if (qFront == nullptr) qRear = nullptr; // <-- the line people drop
delete t;
count--;
return true;
}
};4a. Queue — the dangling rear pointer
Costliest mistake: not resetting qRear = nullptr when the last element leaves. The queue reports empty, but qRear dangles at freed memory and the next enqueue writes through it.
4b. Queue — circular queue
The array version, with every index advance taken modulo capacity.
class CircularQueue {
int* arr; int capacity, front, rear;
public:
CircularQueue(int cap) : capacity(cap), front(0), rear(0) { arr = new int[cap]; }
~CircularQueue() { delete[] arr; }
bool isEmpty() const { return front == rear; }
bool isFull() const { return (rear + 1) % capacity == front; }
int size() const { return (rear - front + capacity) % capacity; }
bool enqueue(int v) {
if (isFull()) return false;
arr[rear] = v;
rear = (rear + 1) % capacity;
return true;
}
bool dequeue(int& out) {
if (isEmpty()) return false;
out = arr[front];
front = (front + 1) % capacity;
return true;
}
};4b. Queue — the four formulas and a real trace
The formulas — memorise these four:
| Test | Sacrificed-slot version | Counter version |
|---|---|---|
| Empty | front == rear | count == 0 |
| Full | (rear + 1) % capacity == front | count == capacity |
| Advance rear | rear = (rear + 1) % capacity | same |
| Advance front | front = (front + 1) % capacity | same |
| Usable slots | capacity - 1 | capacity |
Real trace, capacity = 5:
start front=0 rear=0 size=0 empty=Y full=N
enq 10,20,30,40 front=0 rear=4 size=4 empty=N full=Y
enqueue(50) accepted? no
deq twice front=2 rear=4 size=2 empty=N full=N
enq 50,60 front=2 rear=1 size=4 empty=N full=YNote rear wrapped from 4 to 1 — that is the whole point.
Why circular at all (the essay answer): a simple linear array queue suffers false overflow. After dequeues, front moves forward and leaves free slots at the start, but once rear reaches MAX - 1 the queue refuses new elements even though the array is mostly empty. Fixing it by shifting everything down is O(n) per dequeue. A circular queue wraps the indices with % capacity and reuses those slots in O(1).
Costliest mistake: if you do not sacrifice a slot and do not keep a counter, front == rear means both "empty" and "full" and the two states are indistinguishable.
5. Tree / BST — terminology
Get these exact.
| Term | Definition |
|---|---|
| Degree of a node | number of children |
| Degree of the tree | maximum degree of any node |
| Leaf / external node | degree 0 |
| Internal node | degree ≥ 1 |
| Level of root | 0 (some texts use 1 — state your convention) |
| Depth of a node | edges from root down to that node; root depth = 0 |
| Height of a node | edges on longest path from that node down to a leaf; leaf height = 0 |
| Height of the tree | height of the root = maximum depth of any node |
| Empty tree | height -1 (edge convention) |
| Max nodes at level L | 2^L |
| Max nodes in tree of height h | 2^(h+1) − 1 |
Depth counts downward from the root, height counts upward from the leaves. They are equal only at the root.
struct TreeNode {
int data;
TreeNode* left;
TreeNode* right;
TreeNode(int v) : data(v), left(nullptr), right(nullptr) {}
};5. Tree / BST — operations
Insert, search, height, leaf count, the three depth-first traversals, and level order.
TreeNode* insertBST(TreeNode* root, int v) {
if (root == nullptr) return new TreeNode(v); // base case creates the node
if (v < root->data) root->left = insertBST(root->left, v);
else root->right = insertBST(root->right, v);
return root; // re-attach on the way back up
}
bool searchBST(TreeNode* root, int target) {
if (root == nullptr) return false;
if (root->data == target) return true;
if (target < root->data) return searchBST(root->left, target);
return searchBST(root->right, target);
}
int height(TreeNode* r) { // edge convention
if (r == nullptr) return -1;
return 1 + max(height(r->left), height(r->right));
}
int countLeaves(TreeNode* r) {
if (r == nullptr) return 0;
if (r->left == nullptr && r->right == nullptr) return 1;
return countLeaves(r->left) + countLeaves(r->right);
}
void inorder(TreeNode* r) { if (!r) return; inorder(r->left); cout << r->data << " "; inorder(r->right); }
void preorder(TreeNode* r) { if (!r) return; cout << r->data << " "; preorder(r->left); preorder(r->right); }
void postorder(TreeNode* r){ if (!r) return; postorder(r->left); postorder(r->right); cout << r->data << " "; }
void levelOrder(TreeNode* root) { // uses a QUEUE, not recursion
if (!root) return;
queue<TreeNode*> q; q.push(root);
while (!q.empty()) {
TreeNode* cur = q.front(); q.pop();
cout << cur->data << " ";
if (cur->left) q.push(cur->left);
if (cur->right) q.push(cur->right);
}
}5. Tree / BST — insert rule, real output, complexity
BST insert rule: value < node->data → go left, otherwise go right. New nodes always become leaves; nothing already in the tree moves.
Inserting 50, 30, 70, 20, 40, 60, 80, 35 gives this real output:
inorder: 20 30 35 40 50 60 70 80
preorder: 50 30 20 40 35 70 60 80
postorder: 20 35 40 30 60 80 70 50
levelorder: 50 30 70 20 40 60 80 35
height(edges)=3 leaves=4 search(40)=found search(45)=not found| Operation | Balanced BST | Degenerate (sorted input) |
|---|---|---|
| Search / insert / delete | O(log n) | O(n) |
| Any traversal | O(n) | O(n) |
The check that catches errors: in-order on a BST must come out in ascending order. If it does not, your tree is wrong — redo it before answering anything else.
Costliest mistake: mixing up height and depth, and off-by-one from the two conventions. Say which one you are using ("height in edges, empty tree = −1") and stay consistent across the whole answer.
6. Graph — representation
| Representation | Space | Edge exists? | List neighbours |
|---|---|---|---|
| Adjacency matrix | O(V²) | O(1) | O(V) |
| Adjacency list | O(V + E) | O(deg v) | O(deg v) |
// adjacency list — preferred for sparse graphs
vector<vector<int>> adj(V);
void addEdgeUndirected(vector<vector<int>>& adj, int u, int w) {
adj[u].push_back(w);
adj[w].push_back(u); // BOTH directions
}
void addArcDirected(vector<vector<int>>& adj, int u, int w) {
adj[u].push_back(w); // one direction only
}6. Graph — degree
| Graph | Rule |
|---|---|
| Undirected | degree(v) = edges touching v; a self-loop counts 2; Σ degrees = 2E |
| Directed | in-degree = arcs arriving; out-degree = arcs leaving; total = in + out |
| Directed sum | Σ in-degrees = Σ out-degrees = E |
For the directed graph A→B, A→C, C→B, B→D, C→D, C→E, D→E (7 arcs):
| Vertex | In | Out | Total |
|---|---|---|---|
| A | 0 | 2 | 2 |
| B | 2 | 1 | 3 |
| C | 1 | 3 | 4 |
| D | 2 | 1 | 3 |
| E | 2 | 0 | 2 |
| Σ | 7 | 7 | 14 |
Use Σin = Σout = E as your instant self-check.
6. Graph — breadth-first traversal
Breadth-first traversal is driven by a queue.
vector<bool> visited(V, false);
queue<int> q;
visited[start] = true; // mark WHEN ENQUEUEING
q.push(start);
while (!q.empty()) {
int u = q.front(); q.pop();
cout << u << " ";
for (int w : adj[u]) {
if (!visited[w]) { visited[w] = true; q.push(w); }
}
}6. Graph — the BFT marking trap
Costliest mistake: marking a vertex visited when you dequeue it instead of when you enqueue it. A vertex with two unvisited-at-the-time neighbours then gets pushed twice and appears twice in the output.
DFS is the same code with a stack instead of a queue (or recursion).
6. Graph — Dijkstra
Relaxation step — the one line the whole question turns on:
if
dist[u] + weight(u, v) < dist[v]thendist[v] = dist[u] + weight(u, v)andparent[v] = u
Loop: pick the unsettled vertex with the smallest dist, mark it settled (its distance is now final), relax all its outgoing edges, repeat.
vector<int> dist(V, INT_MAX), parent(V, -1);
vector<bool> done(V, false);
dist[src] = 0;
for (int it = 0; it < V; it++) {
int u = -1;
for (int i = 0; i < V; i++)
if (!done[i] && dist[i] != INT_MAX && (u == -1 || dist[i] < dist[u])) u = i;
if (u == -1) break;
done[u] = true;
for (auto& e : adj[u]) { // e = {neighbour, weight}
int v = e.first, w = e.second;
if (!done[v] && dist[u] + w < dist[v]) { dist[v] = dist[u] + w; parent[v] = u; }
}
}6. Graph — Dijkstra complexity and limits
| Version | Complexity |
|---|---|
| Array scan for the minimum | O(V²) |
| Binary heap / priority queue | O((V + E) log V) |
Costliest mistake: using Dijkstra on a graph with a negative edge weight. Once a vertex is settled its distance is never revisited, so a negative edge can produce a wrong answer. Say "Bellman-Ford" if negative weights appear.
6. Graph — Kruskal (MST)
- Sort all edges by weight, ascending.
- Take the next cheapest edge; keep it only if it joins two different components (no cycle).
- Stop at V − 1 edges.
Cycle detection with union-find. Contrast: Prim's grows one tree from a start vertex (vertex-based); Kruskal's picks globally cheapest edges (edge-based). Both give the same total weight.
7. Sorting
Bubble, selection and insertion, written the way they are marked.
void bubbleSort(int a[], int n) {
for (int i = 0; i < n - 1; i++) {
bool swapped = false;
for (int j = 0; j < n - 1 - i; j++)
if (a[j] > a[j + 1]) { swap(a[j], a[j + 1]); swapped = true; }
if (!swapped) break; // makes best case O(n)
}
}
void selectionSort(int a[], int n) {
for (int i = 0; i < n - 1; i++) {
int minIdx = i;
for (int j = i + 1; j < n; j++) if (a[j] < a[minIdx]) minIdx = j;
if (minIdx != i) swap(a[i], a[minIdx]);
}
}
void insertionSort(int a[], int n) {
for (int i = 1; i < n; i++) {
int key = a[i], j = i - 1;
while (j >= 0 && a[j] > key) { a[j + 1] = a[j]; j--; }
a[j + 1] = key;
}
}7. Sorting — comparison table and a real trace
| Algorithm | Best | Average | Worst | Space | Stable |
|---|---|---|---|---|---|
| Bubble (with flag) | O(n) | O(n²) | O(n²) | O(1) | Yes |
| Selection | O(n²) | O(n²) | O(n²) | O(1) | No |
| Insertion | O(n) | O(n²) | O(n²) | O(1) | Yes |
| Merge | O(n log n) | O(n log n) | O(n log n) | O(n) | Yes |
| Quick | O(n log n) | O(n log n) | O(n²) | O(log n) | No |
Real bubble-sort passes on 5 1 4 2 8:
pass 1: 1 4 2 5 8
pass 2: 1 2 4 5 8
pass 3: 1 2 4 5 8 (no swap -> stop early)Costliest mistake: the inner bound. It is j < n - 1 - i, not j < n - 1. Without - i you re-compare the already-sorted tail; with j <= n - 1 you read a[n] off the end.
8. Searching
Binary search, in the form that survives marking.
int binarySearch(const int a[], int n, int target) {
int low = 0, high = n - 1;
while (low <= high) { // <=, not <
int mid = low + (high - low) / 2; // overflow-safe form
if (a[mid] == target) return mid;
else if (a[mid] < target) low = mid + 1;
else high = mid - 1;
}
return -1;
}8. Searching — comparison and the loop-bound trap
| Algorithm | Best | Worst | Requires |
|---|---|---|---|
| Linear search | O(1) | O(n) | nothing |
| Binary search | O(1) | O(log n) | sorted array, random access |
On 2 5 8 12 16 23 38 56 72 91 the compiled program prints: index of 23 = 5, index of 24 = -1, linear index of 56 = 7.
Costliest mistake: while (low < high) or low = mid / high = mid. The first misses the last candidate; the second loops forever when low and high are adjacent.
Worked trace A — infix to postfix: P - Q / (R + S) * T
Rules: operand → output. ( → push. ) → pop to output until (, discard (. Operator → while the stack top is an operator of higher or equal precedence, pop it to output; then push. End → pop everything.
| Read | Action | Stack (bottom→top) | Output |
|---|---|---|---|
P | operand | — | P |
- | stack empty, push | - | P |
Q | operand | - | PQ |
/ | - is lower, push | -/ | PQ |
( | push | -/( | PQ |
R | operand | -/( | PQR |
+ | top is (, push | -/(+ | PQR |
S | operand | -/(+ | PQRS |
) | pop +, discard ( | -/ | PQRS+ |
* | / equal precedence → pop it; - lower → push * | -* | PQRS+/ |
T | operand | -* | PQRS+/T |
| end | pop *, then - | — | PQRS+/T*- |
Answer: PQRS+/T*- (verified by the compiled program).
Two traps: ( is never sent to the output, and equal precedence pops (left-associative), which is what makes / come out before *.
Worked trace B — BFT queue state, start = 0
Undirected graph: 0–1, 0–2, 1–3, 1–4, 2–4, 3–5, 4–5.
| Step | Dequeue | Newly visited (enqueued) | Queue after (front→back) |
|---|---|---|---|
| 0 | — | 0 | 0 |
| 1 | 0 | 1, 2 | 1 2 |
| 2 | 1 | 3, 4 | 2 3 4 |
| 3 | 2 | — (4 already visited) | 3 4 |
| 4 | 3 | 5 | 4 5 |
| 5 | 4 | — | 5 |
| 6 | 5 | — | empty |
Visit order: 0 1 2 3 4 5. Step 3 is the mark: 2's neighbour 4 was already marked at step 2, so it is not enqueued again.
Worked trace C — Dijkstra table, source A
Directed, weighted: A→B 4, A→C 2, C→B 1, B→D 5, C→D 7, C→E 10, D→E 3.
| Settle | A | B | C | D | E | What changed |
|---|---|---|---|---|---|---|
| init | 0 | ∞ | ∞ | ∞ | ∞ | |
| A (0) | 0 | 4 | 2 | ∞ | ∞ | B←4 via A, C←2 via A |
| C (2) | 0 | 3 | 2 | 9 | 12 | B improved 4→3 via C, D←9, E←12 |
| B (3) | 0 | 3 | 2 | 8 | 12 | D improved 9→8 via B |
| D (8) | 0 | 3 | 2 | 8 | 11 | E improved 12→11 via D |
| E (11) | 0 | 3 | 2 | 8 | 11 | nothing left |
Shortest path A→E = A→C→B→D→E, cost 11 (2+1+5+3). All values are real program output.
The teaching point is row 2: the direct arc A→B cost 4, but going through C cost 3. Always pick the smallest unsettled distance next, and always re-check whether a shorter route just appeared.
If you only have twenty minutes
- Circular queue tests. Empty
front == rear; full(rear + 1) % capacity == front; advance with% capacity; capacity − 1 usable. - Postfix operand order. First pop = right operand. Second pop = left.
- Height vs depth. Depth counts down from the root (root = 0); height counts up from the leaves (leaf = 0, empty = −1).
- BST insert rule.
<goes left, otherwise right; new nodes are always leaves; in-order must come out ascending. - Mark visited on enqueue in BFT, never on dequeue.
- Dijkstra relaxation.
if (dist[u] + w < dist[v]) dist[v] = dist[u] + w;and settle the smallest unsettled vertex each round. - Reset
rear = nullptrwhen a linked queue empties. head = prev;at the end of an in-place list reverse.- Degree checks. Undirected Σdeg = 2E; directed Σin = Σout = E.
- Complexities worth memorising cold. Array access O(1); list search O(n); stack/queue ops O(1); balanced BST O(log n) but degenerate O(n); binary search O(log n) and it needs a sorted array; bubble/selection/insertion O(n²), merge O(n log n).
- Precedence.
^>* />+ -;(is never output; equal precedence pops. - Write the struct first. In a code question the node declaration and the null checks are marks on their own — put them down even if the algorithm body stalls.
Good luck. Sleep beats one more re-read.
Which C++ standard does this page assume?
Standard C++17. C++ began as C with Classes in 1979 and first shipped commercially in 1985; what a compiler flag actually selects today is one of the ISO revisions below, and the committee has published a new one every 3 years since 2011. Build these listings with -std=c++17 and they compile as written.
| Revision | Published as | What it changes for the code on this page |
|---|---|---|
| C++98 | ISO/IEC 14882:1998 | The first ISO C++, and the dialect most data-structures courses still teach from: templates, the STL containers, and raw pointers doing the work. |
| C++03 | ISO/IEC 14882:2003 | A defect-fix revision. Nothing on these pages depends on it, and nothing on these pages is broken by it. |
| C++11 | ISO/IEC 14882:2011 | Where nullptr, auto, range-based for, move semantics and the unordered containers arrive. Every listing here writes nullptr rather than NULL because of it. |
| C++14 | ISO/IEC 14882:2014 | A small revision: generic lambdas and std::make_unique. Used only where it makes ownership clearer. |
| C++17 | ISO/IEC 14882:2017 | What every listing on StuHub targets and was compiled against. If you build these files, build them with -std=c++17. |
| C++20 | ISO/IEC 14882:2020 | Concepts, ranges and std::midpoint. Flagged in the prose where it offers a shorter correct form, never assumed by the code. |
| C++23 | ISO/IEC 14882:2024 | Not used here. Named so you can tell whether a snippet you found elsewhere will compile on a lab machine that predates it. |
Common questions
What does this page cover?
Night-before reference for a data structures exam: declarations, complexity tables, the rule that decides each answer, and worked traces in C++.
How long does this page take to work through?
About 13 minutes of reading at 200 words per minute, plus 0 questions with worked solutions at the foot of the page. Reading it end to end is the slow way; the intended use is to find the section you are stuck on, then do the questions for that section with the solutions covered.
Which C++ standard do these examples target?
Standard C++17 — ISO/IEC 14882:2017. Every listing was compiled with -std=c++17 and -Wall -Wextra before publication, and the linked-structure examples were also run under AddressSanitizer. Where C++20 offers a shorter correct form, such as std::midpoint, the prose says so instead of quietly using it.
Is StuHub free, and do I need an account?
It is free and there is nothing to sign in to. No login, account or payment is required to read any of the 20 topics — StuHub is published by DUOCODE TECHNOLOGY alongside APRide, and the ride board's accounts have nothing to do with it.
Can I paste this code into my assignment?
Treat it as a reference, not as an answer key. StuHub is educational material only, it is not coursework and it is not affiliated with or endorsed by any institution, so your own submission rules decide what you may reuse. Every listing was compiled and run before publication, and you should still compile and test anything you take.
Why is everything written in C++ rather than pseudocode?
Because most of the mistakes worth catching are C++ mistakes, not algorithm mistakes: a lost pointer, a destructor that never runs, an index that underflows because it was unsigned. Pseudocode hides exactly the layer where a data-structures assignment is actually failed.
Where should I check what the standard library really guarantees?
cppreference for the day-to-day answer, and the WG21 working drafts when the exact wording matters — both are linked below. Compiler documentation settles the rest: a warning you cannot explain is usually the compiler being right.
Does StuHub replace my lecture notes?
No. It is written to sit beside them: your course decides what is examinable, in what notation, and with which library restrictions. Where this page and your module handbook disagree about scope, the handbook wins.
Is StuHub connected to Asia Pacific University?
No. It is an independent reference published by DUOCODE TECHNOLOGY, not affiliated with or endorsed by Asia Pacific University or any other institution. It was written for APU students because that is who asked for it, and it is open to anyone.
Where can I check this against the language itself?
Nothing on this page outranks the standard or the library reference. When this page and one of these disagree, they are right and we want to know.
- cppreference — the C++ standard library referenceThe fastest correct answer for what a container or algorithm actually guarantees.
- isocpp.org — the Standard C++ FoundationThe FAQ and the core guidelines, written by the people who define the language.
- ISO/IEC JTC1/SC22/WG21 — the C++ standards committeeWorking drafts of the standard itself, free to read, when the wording is the question.
- GCC online documentationWhat -Wall, -Wextra and the sanitizers used on these listings actually check.
- Microsoft Learn — C++ language documentationThe MSVC view, for readers whose lab machines build with Visual Studio.
Published 2026-08-09 · updated 2026-08-27 · DUOCODE TECHNOLOGY