Checkpoint: Data & Memory
You've learned vectors, maps/sets, smart pointers, lambdas, auto, range-for, structs and const/constexpr — let's combine them. This checkpoint isn't a new topic; it's the moment where the last several lessons click together into the way real C++ programs are actually written: model data with structs, hold records in a vector, sort and tally them, and manage memory safely.
Learn Checkpoint: Data & Memory in our free C++ course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.
Part of the free C++ course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
A quick map of the toolkit you're now carrying into the build challenge:
Almost every data-handling program follows the same shape you've now learned piece by piece: (1) describe one record with a struct , (2) keep many of them in a std::vector , (3) sort or filter them with a lambda , (4) summarize with a std::map , and (5) manage any heap objects with a smart pointer — all glued together with auto , range-based for , and const -correctness. Carts, leaderboards, inventories, analytics dashboards: under the hood, this is the pattern.
A Quick Tour — Everything Together
Before the challenge, run this short program. It uses every tool from the section in one tidy flow: a struct for a product, a vector of them, a lambda sort, a range-based for with auto , a map tally, and a unique_ptr . If you can read every line comfortably, you're ready.
These lines build a vector of structs, sort it with a lambda, and print the first. Put them in order:
Define the P struct before main (B), open main (E), build the vector (C), sort descending by score with a lambda (A), print the highest scorer's name — Bo (D), then return 0; (F) and close (G).
Time to put it all together in one multi-step program. You're given a vector of Order structs. Work through the four steps in the starter — each one exercises a different tool you've learned:
Try it yourself first, then reveal the full solution to compare.
One worked solution. It even adds a const total() member to the struct to keep the comparator and printing tidy. Run it and read the expected output in the comment at the bottom.
⏱ Timed Quiz
Answer each in your head, then reveal it. These cover the whole section.
1. You have a and want them sorted by score descending. What do you pass to std::sort ?
A lambda comparator that returns true when the first should come first: [](const Student& a, const Student& b){' '} . Returning > gives descending order.
2. Which container counts how many items belong to each category, and what's the one-line tally idiom?
A (or unordered_map ). The idiom is ++counts[category]; — a missing key is value-initialized to 0 first.
3. Why use make_unique<Order>(...) instead of new Order(...) ?
The unique_ptr frees the object automatically when it goes out of scope — no manual delete , no leaks or double-frees. make_unique is also exception-safe and avoids writing raw new .
4. In for (const auto& o : orders) , why const auto& rather than plain auto ?
const auto& reads each Order without copying it (the & ) and promises not to modify it (the const ). Plain auto would copy every struct on each iteration.
5. What's the difference between const and constexpr for a value like a maximum size?
const means it can't be reassigned (may be set at run time); constexpr guarantees it's known at compile time, so it can size a fixed array. Use constexpr when you need a true compile-time constant.
6. After sort(...) by value descending, where is the most valuable order, and how do you copy it into a smart pointer?
It's at the front: orders.front() (i.e. orders[0] ). Copy it with auto top = make_unique<Order>(orders.front()); , then access fields via top-> .
Practice quiz
Which std::vector member function adds an element to the end of the vector?
- push_front
- append
- push_back
- insert_back
Answer: push_back. std::vector grows from the end with push_back; there is no push_front.
To sort a vector of structs by a field in descending order, what do you pass as the third argument to std::sort?
- A lambda comparator returning a.field > b.field
- The field name as a string
- The vector's .size()
- Nothing — sort always descends
Answer: A lambda comparator returning a.field > b.field. std::sort takes a comparator; a lambda returning a.field > b.field gives descending order.
In a range-based for loop, why prefer 'const auto& x' over plain 'auto x' when only reading elements?
- It runs the loop in parallel
- It is required for std::map
- auto is not allowed in range-for
- It avoids copying each element and prevents accidental modification
Answer: It avoids copying each element and prevents accidental modification. const auto& binds a reference so no copy is made, and const forbids modifying the element.
What does the expression ++counts[category] do when 'category' is not yet a key in a std::map<string,int>?
- Throws an out_of_range exception
- Inserts the key with value 0, then increments it to 1
- Does nothing
- Increments a random existing entry
Answer: Inserts the key with value 0, then increments it to 1. operator[] value-initializes a missing key to 0, then ++ makes it 1 — the classic tally idiom.
Which header must be included to use std::sort?
- <algorithm>
- <vector>
- <map>
- <memory>
Answer: <algorithm>. std::sort lives in <algorithm>, separate from the container headers.
What is the main advantage of std::make_unique<T>(...) over 'new T(...)'?
- It is faster at runtime
- It allows the object to be shared by many owners
- It frees the object automatically when the unique_ptr goes out of scope
- It allocates on the stack instead of the heap
Answer: It frees the object automatically when the unique_ptr goes out of scope. A unique_ptr ties the heap object's lifetime to scope, freeing it automatically with no manual delete.
How do you access a member of an object owned by a std::unique_ptr<Order> named 'top'?
- top.member
- top->member
- top::member
- *top.member
Answer: top->member. A smart pointer is dereferenced with ->, just like a raw pointer, e.g. top->customer.
What does a struct give you in C++?
- Automatic memory cleanup
- A growable list of elements
- A compile-time constant
- A way to bundle related fields into one record type
Answer: A way to bundle related fields into one record type. A struct groups related data fields together into a single named record type.
What is the difference between 'const' and 'constexpr' for a value?
- They are identical
- const means it cannot be reassigned; constexpr also guarantees the value is known at compile time
- constexpr values can be reassigned but const cannot
- const works only with integers
Answer: const means it cannot be reassigned; constexpr also guarantees the value is known at compile time. constexpr is a stronger guarantee — a true compile-time constant usable to size fixed arrays.
After sorting a vector descending by value, where is the most valuable element?
- At v.back()
- At the middle index
- At v.front() (index 0)
- It must be searched for with std::find
Answer: At v.front() (index 0). A descending sort puts the largest element first, so it is at v.front(), i.e. v[0].