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].