🌍 C++ Programming · subject

C++ Programming Best Practices Syllabus

The Best Practices syllabus for C++ Programming in full: 3 chapters and 6 topics, every one listed below, plus 51 Best Practices flashcards with answers.

3Chapters
6Topics
51Flashcards

Best Practices syllabus: all 3 chapters

Expand any chapter to see its topics and sub-topics.

  1. Code Optimization

    2 topics
    • Memory Management
    • Efficient Algorithms
  2. Code Readability

    2 topics
    • Naming Conventions
    • Commenting and Documentation
  3. Testing and Debugging

    2 topics
    • Unit Testing
    • Debugging Techniques

C++ Programming Best Practices flashcards — 51 questions with answers

  1. What is the core distinction between the stack and the heap in C++ memory management?

    The stack stores automatic (local) variables with automatic storage duration, is managed by the compiler, and is fast (LIFO). The heap (free store) stores dynamically allocated objects that persist until explicitly freed, is manually managed, and is slower.

  2. In C++, which operator pairs must be matched to avoid undefined behavior when freeing dynamic memory?

    Use `delete` with memory from `new`, and `delete[]` with memory from `new[]`. Mismatching them (e.g., `delete` on a `new[]` array) is undefined behavior.

  3. Define a memory leak in C++ and give its primary cause.

    A memory leak is heap memory that is allocated but never deallocated, so it remains reserved for the program's lifetime. It is caused by losing all pointers to a block (e.g., overwriting or letting a pointer go out of scope) before calling `delete`.

  4. What does RAII stand for, and what problem does it solve?

    RAII means Resource Acquisition Is Initialization. A resource (memory, file, lock) is tied to an object's lifetime: acquired in the constructor and released in the destructor, so it is automatically freed when the object goes out of scope, preventing leaks even during exceptions.

  5. Compare `std::unique_ptr` and `std::shared_ptr`.

    `unique_ptr` provides exclusive, non-copyable ownership of a resource (movable only) with zero overhead. `shared_ptr` provides shared ownership via a reference count; the resource is freed when the count reaches zero, at the cost of atomic counting overhead.

  6. What is the purpose of `std::weak_ptr` and which problem does it prevent?

    `std::weak_ptr` is a non-owning reference to an object managed by a `shared_ptr`; it does not affect the reference count. It prevents cyclic reference leaks, where two `shared_ptr`s pointing to each other keep the count above zero forever.

  7. What is a dangling pointer?

    A dangling pointer is a pointer that still references memory that has already been freed (or an object that has gone out of scope). Dereferencing it is undefined behavior.

  8. What is the difference between shallow copy and deep copy in C++?

    A shallow copy duplicates pointer values, so both objects share the same underlying memory (risking double-free). A deep copy allocates new memory and copies the pointed-to data, giving each object its own independent resources.

  9. State the Rule of Three in C++.

    If a class needs a user-defined destructor, copy constructor, or copy assignment operator, it almost certainly needs all three, because it manages a resource that requires custom copy/cleanup semantics.

  10. State the Rule of Five in modern C++.

    If a class defines any of the destructor, copy constructor, copy assignment, it should also consider the move constructor and move assignment operator; managing a resource typically requires all five special member functions.

  11. What is Big O notation used to describe?

    Big O notation describes the asymptotic upper bound on an algorithm's running time or space usage as a function of input size $n$, characterizing worst-case growth while ignoring constants and lower-order terms.

  12. Order these common complexities from fastest to slowest growth: $O(n^{2})$, $O(1)$, $O(n \log n)$, $O(\log n)$, $O(n)$, $O(2^{n})$.

    $O(1) < O(\log n) < O(n) < O(n \log n) < O(n^{2}) < O(2^{n})$.

  13. What is the average and worst-case time complexity of QuickSort?

    Average case is $O(n \log n)$; worst case is $O(n^{2})$, occurring when pivot choices are consistently poor (e.g., already-sorted input with a naive pivot).

  14. What is the time complexity of binary search, and what precondition does it require?

    Binary search runs in $O(\log n)$ time and requires the data to be sorted.

  15. What is the average-case lookup complexity of a hash table (e.g., `std::unordered_map`)?

    $O(1)$ on average for insertion, deletion, and lookup, degrading to $O(n)$ in the worst case when many keys collide into the same bucket.

  16. Distinguish time complexity from space complexity.

    Time complexity measures how the number of operations grows with input size; space complexity measures how the amount of additional memory grows with input size. Both are typically expressed in Big O notation.

  17. What is the difference between Big O, Big Omega ($\Omega$), and Big Theta ($\Theta$)?

    Big O ($O$) is an asymptotic upper bound, Big Omega ($\Omega$) is a lower bound, and Big Theta ($\Theta$) is a tight bound that holds when the upper and lower bounds match.

  18. Give the time complexity of accessing an element by index in a `std::vector` versus a `std::list`.

    `std::vector` (contiguous array) gives $O(1)$ random access by index. `std::list` (doubly linked list) requires $O(n)$ traversal to reach an arbitrary element.

  19. Why is the amortized cost of `push_back` on a `std::vector` $O(1)$ despite occasional reallocation?

    The vector grows its capacity geometrically (e.g., doubling), so reallocations are rare and their total cost spread over $n$ insertions averages to $O(1)$ per element (amortized analysis).

  20. What is the time complexity of Merge Sort in all cases, and what is its main drawback versus QuickSort?

    Merge Sort is $O(n \log n)$ in best, average, and worst cases. Its drawback is requiring $O(n)$ extra space, whereas QuickSort can sort in place.

Show the other 31 Best Practices flashcards
  1. What is the difference between an iterative and a recursive algorithm, and what runtime resource does recursion consume?

    An iterative algorithm uses loops; a recursive algorithm calls itself with smaller inputs. Recursion consumes stack memory for each call frame, and deep recursion risks stack overflow.

  2. What are the three most common identifier naming case styles, with an example of each?

    camelCase (e.g., `studentCount`), PascalCase / UpperCamelCase (e.g., `StudentRecord`), and snake_case (e.g., `student_count`). SCREAMING_SNAKE_CASE (e.g., `MAX_SIZE`) is common for constants/macros.

  3. What naming convention is conventionally used for C++ class and type names in most style guides?

    PascalCase (UpperCamelCase), e.g., `BankAccount`, `LinkedList`, distinguishing types from variables and functions.

  4. By common C++ convention, how are compile-time constants and macros typically named?

    In SCREAMING_SNAKE_CASE (all uppercase with underscores), e.g., `#define MAX_BUFFER 1024` or `const int MAX_USERS = 100;`.

  5. What is Hungarian notation and why is it often discouraged in modern C++?

    Hungarian notation prefixes a variable's name with a type/kind indicator (e.g., `iCount`, `strName`). It is discouraged because modern IDEs and strong typing make it redundant, and it becomes misleading when types change.

  6. What is the recommended practice for boolean variable and function names?

    Name them as predicates that read as yes/no questions, using prefixes like `is`, `has`, `can`, or `should` (e.g., `isValid`, `hasNext`, `canDelete`).

  7. Why should single-letter variable names generally be avoided, and what is a common exception?

    Single-letter names obscure intent and hurt readability. The common exception is short-lived loop counters or indices such as `i`, `j`, `k`, where the meaning is conventional and local.

  8. What is the key principle behind choosing good identifier names?

    Names should be self-documenting and intention-revealing: describe what the entity represents or does, so code reads clearly without extra comments. Favor clarity over brevity.

  9. What is the difference between a `//` comment and a `/* */` comment in C++?

    `//` starts a single-line comment that runs to the end of the line. `/* */` delimits a block comment that can span multiple lines and cannot be nested.

  10. What distinguishes a documentation comment from an ordinary implementation comment?

    Documentation comments (often `///` or `/** */` for Doxygen) describe the public interface — what a function/class does, its parameters, return value, and contract — for API consumers. Implementation comments explain the why of internal code for maintainers.

  11. What is Doxygen, and name two common Doxygen tags.

    Doxygen is a tool that generates API documentation from specially formatted source comments. Common tags include `@param` (describe a parameter), `@return` (describe the return value), `@brief`, and `@throws`.

  12. According to best practice, should comments explain what the code does or why it does it, and why?

    Comments should primarily explain the why (intent, rationale, trade-offs, non-obvious constraints). The what should be evident from well-named, clear code; restating it makes comments redundant and prone to going stale.

  13. What is the main risk of over-commenting or leaving outdated comments?

    Redundant comments add noise, and outdated comments actively mislead readers because the compiler never checks them against the code, causing them to drift out of sync with behavior.

  14. What is a unit test?

    A unit test is an automated test that verifies the smallest testable piece of code (typically a single function or class) in isolation, checking that given specific inputs it produces the expected outputs.

  15. What do the three phases Arrange, Act, Assert (AAA) mean in a unit test?

    Arrange: set up the objects and inputs (fixtures). Act: invoke the function or behavior under test. Assert: verify the actual result matches the expected result.

  16. What is a test fixture?

    A test fixture is the fixed baseline state and set-up code (objects, data, environment) established before running tests, so each test runs against a known, consistent context.

  17. What is a mock object and why is it used in unit testing?

    A mock is a substitute for a real dependency that simulates its behavior and records interactions. It isolates the unit under test from external systems (databases, networks) and lets you verify how the unit uses its collaborators.

  18. What does code coverage measure, and does 100% coverage guarantee correctness?

    Code coverage measures the percentage of code (lines, branches, functions) executed by the test suite. 100% coverage does not guarantee correctness — it only means code ran, not that all behaviors and edge cases were correctly asserted.

  19. Name two popular C++ unit testing frameworks.

    Google Test (gtest), Catch2, Boost.Test, and doctest are widely used C++ unit testing frameworks.

  20. In Test-Driven Development (TDD), what is the Red-Green-Refactor cycle?

    Red: write a failing test for new behavior. Green: write the minimum code to make it pass. Refactor: clean up the code while keeping the test passing. Repeat.

  21. What is a regression test?

    A regression test verifies that previously working functionality still works after code changes, catching bugs (regressions) reintroduced by new development or refactoring.

  22. Distinguish unit tests from integration tests.

    Unit tests verify a single component in isolation (dependencies mocked). Integration tests verify that multiple components work correctly together, including their real interactions and interfaces.

  23. What is a breakpoint in a debugger?

    A breakpoint is a marker set at a specific line or condition that pauses program execution when reached, letting the developer inspect the current state (variables, call stack) at that point.

  24. What is the difference between 'step into', 'step over', and 'step out' when debugging?

    Step into enters a called function to debug it line by line. Step over executes the called function as a single step without entering it. Step out runs the rest of the current function and returns to its caller.

  25. Name two common command-line debuggers used with C++.

    GDB (GNU Debugger) and LLDB (the LLVM debugger). On Windows, the Visual Studio debugger / WinDbg are also common.

  26. What is a watchpoint (data breakpoint) in debugging?

    A watchpoint pauses execution whenever the value of a specified variable or memory location changes (or is read), rather than when a particular line is reached, helping track down unexpected mutations.

  27. What is a segmentation fault and a typical cause?

    A segmentation fault is a runtime error where a program accesses memory it is not allowed to. Typical causes include dereferencing a null or dangling pointer, out-of-bounds array access, or stack overflow.

  28. What is Valgrind (or a memory sanitizer) used for in C++ debugging?

    Tools like Valgrind's Memcheck and compiler sanitizers (AddressSanitizer) detect memory errors at runtime — leaks, invalid reads/writes, use-after-free, and uninitialized memory access.

  29. What is 'rubber duck debugging'?

    Rubber duck debugging is explaining your code line by line, out loud, to an inanimate object (a rubber duck). Articulating the logic forces you to examine assumptions and often reveals the bug yourself.

  30. What does 'undefined behavior' (UB) mean in C++, and why does it make debugging hard?

    Undefined behavior is code whose result the C++ standard does not define (e.g., signed overflow, out-of-bounds access, use-after-free). Compilers may do anything, so programs can appear to work, crash randomly, or behave differently across builds, making bugs non-deterministic and hard to reproduce.

  31. What is a core dump and how is it useful for debugging?

    A core dump is a file capturing a program's memory state at the moment it crashed. Loaded into a debugger (e.g., GDB), it lets you perform postmortem analysis — inspect the call stack and variables to find the cause of a crash after the fact.

C++ Programming Best Practices FAQ

What is in the C++ Programming Best Practices syllabus?

C++ Programming Best Practices is split into 3 chapters: Code Optimization, Code Readability and Testing and Debugging. Together they contain 6 topics.

How many chapters are in C++ Programming Best Practices?

3 chapters, containing 6 topics. The largest chapter is Code Optimization, with 2 topics.

Are there flashcards for C++ Programming Best Practices?

Yes — a 51-card Best Practices deck, printed in full in the flashcards section of this page and available in the Examius app with spaced repetition. The free plan covers one exam of your choice, including its flashcards; Examius Pro, a one-time purchase, unlocks every other exam and deck.