Skip to content

Chapter 31 of 31

Best Practices and Optimization

Build clear, testable, secure, portable C++ and optimize from measured evidence.

40 minutes 10 quick checksBy Subha Prasad
Lesson 31 of 31Course navigation

Lesson content

Read, practise, then check your understanding

Correctness and design come before speed. Give every resource a clear owner, prefer values and RAII, keep scopes small, initialize objects, make invalid states hard to represent, and compile with strong warnings. Use const, constexpr, noexcept, and [[nodiscard]] when they express a real contract.

#include <span>

[[nodiscard]] double average(std::span<const int> values) {
    if (values.empty()) return 0.0;
    long long sum{};
    for (int value : values) sum += value;
    return static_cast<double>(sum) / values.size();
}

Separate interfaces from implementation, favor composition, and use standard containers and algorithms. Avoid owning raw pointers, unchecked indexing at trust boundaries, C-style casts, macros where typed alternatives exist, and undefined behavior. Automate formatting, static analysis, unit/integration tests, and sanitizer builds.

Optimize methodically

Define a performance goal, benchmark a representative workload, profile to find the bottleneck, change one thing, then measure again. Algorithmic improvement usually dominates instruction-level tuning. Data layout and locality often matter more than clever syntax; contiguous vectors frequently outperform node-based containers.

Avoid accidental copies with references or moves, but do not sacrifice lifetime safety. Reserve capacity when growth is predictable, batch I/O, and reduce allocation only where profiles show value. Treat concurrency as a scalability tool with overhead, not a universal speedup. Preserve readable code and regression tests around every optimization so future maintainers can verify both result and reason.

Knowledge check

Answer every question correctly to complete this chapter.

What should guide optimization?
What ownership default should modern C++ prefer?
Why enable broad compiler warnings?
Which tool detects many runtime memory errors?
Why prefer algorithms and ranges to manual loops when clear?
What is the zero-overhead principle?
What should public interfaces make explicit?
Why avoid premature micro-optimization?
Which guideline helps polymorphic bases?
When is optimization unacceptable?

0 of 10 checks passed

Your progress is saved on this device.