MatheLinuxMatheLinux
Curriculum
Sign inStart free
C++ & HPC for Quants
0%

0 of 15 lessons complete

Lessons

  • Types, RAII & Resource Management8m
  • The STL: Containers & Algorithms8m
  • Templates & Generic Programming8m
  • Move Semantics & Performance8m
  • Floating Point & Numerical Stability8m
  • Building a Monte Carlo Pricer8m
  • A Finite-Difference PDE Solver8m
  • Design Patterns for Pricing8m
  • The Memory Hierarchy & Cache8m
  • Vectorization (SIMD)8m
  • Multithreading8m
  • Profiling & Optimization Discipline8m
  • Parallel Monte Carlo8m
  • GPU Computing: The CUDA Model8m
  • Scaling a Pricing Engine8m

MatheLinux — quantitative finance, taught rigorously.

Course content credited to Ibrahim Lanre Adedimeji.

← C++ & HPC for Quants

Why C++ for quants

Pricing engines, risk systems, and execution gateways live or die on two things: predictable performance and deterministic resource handling. C++ gives you both because it exposes the machine model directly: you control whether an object lives on the stack or the heap, whether it is copied or shared, and exactly when its memory and other resources are released. The discipline that makes all of this safe is RAII — Resource Acquisition Is Initialization.

Value vs reference semantics

In C++ a variable of type double is a double; it is not a handle pointing somewhere else. This is value semantics. When you pass a value, you copy it unless you ask otherwise.

#include <iostream>

struct Quote { double bid; double ask; };

void widenCopy(Quote q) { q.ask += 0.01; }      // edits a copy
void widenRef(Quote& q) { q.ask += 0.01; }       // edits the original

int main() {
    Quote eurusd{1.0810, 1.0812};
    widenCopy(eurusd);
    std::cout << eurusd.ask << "\n";  // 1.0812 unchanged
    widenRef(eurusd);
    std::cout << eurusd.ask << "\n";  // 1.0813 changed
    return 0;
}

A reference (Quote&) is an alias for an existing object. Pass large objects by const reference to avoid copies while guaranteeing you will not mutate them: void price(const Quote& q).

Stack vs heap

Objects declared as local variables live on the stack: allocation is a pointer bump, deallocation is automatic when the scope exits, and access is cache-friendly. Objects created with new live on the heap: allocation is slower, lifetime is manual, and you must eventually delete them. In hot quant code you prefer the stack; you reach for the heap only when an object must outlive its scope or its size is decided at runtime.

RAII: tie resources to object lifetime

RAII means a resource (memory, a file handle, a market-data subscription, a lock) is acquired in a constructor and released in the destructor. Because C++ guarantees destructors run when an object leaves scope — even via an exception — RAII makes leaks structurally impossible.

#include <iostream>

class PriceBuffer {
    double* data_;
    std::size_t n_;
public:
    explicit PriceBuffer(std::size_t n) : data_(new double[n]), n_(n) {
        std::cout << "acquire " << n_ << " slots\n";
    }
    ~PriceBuffer() {                       // runs automatically
        delete[] data_;
        std::cout << "release\n";
    }
    double& operator[](std::size_t i) { return data_[i]; }
    std::size_t size() const { return n_; }
};

void useBuffer() {
    PriceBuffer pb(3);
    pb[0] = 100.5;
    // no manual delete; ~PriceBuffer runs at scope exit
}

The constructor acquires; the destructor releases. If useBuffer threw after pb[0] = 100.5, the destructor would still fire during stack unwinding.

Knowledge check

Q1. When does the destructor of a stack-allocated RAII object run?

Q2. Which smart pointer models exclusive ownership with effectively zero runtime overhead?

Q3. Why pass a large struct by const reference rather than by value?

Q4. What does std::shared_ptr use to decide when to free its object?

Problems

P1

Given the PriceBuffer example, a function creates a PriceBuffer of size 2, writes to slot 0, then returns normally. Using the constructor and destructor print statements shown in the lesson, what is printed (write the two lines in order, separated by a newline)?

P2

In the shared_ptr example, after auto alias = shared; the program prints shared.use_count(). What integer is printed?

Mark this lesson complete to track progress

Smart pointers replace raw owning pointers

Hand-written owning classes are rarely needed because the standard library ships RAII wrappers. std::unique_ptr models exclusive ownership and is zero-overhead. std::shared_ptr models shared ownership via reference counting.

#include <memory>
#include <iostream>

struct YieldCurve { double rate(double t) const { return 0.03; } };

int main() {
    auto curve = std::make_unique<YieldCurve>();   // exclusive owner
    std::cout << curve->rate(1.0) << "\n";
    // moved, not copied, when ownership transfers
    auto shared = std::make_shared<YieldCurve>();   // counted owner
    auto alias  = shared;                            // count now 2
    std::cout << shared.use_count() << "\n";        // prints 2
    return 0;
}                                                    // all freed here

Prefer unique_ptr; upgrade to shared_ptr only when several components genuinely co-own a thing (for example a yield curve referenced by many trades). Never call delete on the raw pointer a smart pointer manages.

Why quants care

A mispriced book is bad; a process that leaks file handles overnight and dies during the close auction is catastrophic. RAII converts "remember to clean up" from a human responsibility into a compiler-enforced guarantee, and it composes: a Trade holding a unique_ptr<YieldCurve> and a PriceBuffer cleans up all of it automatically and in the correct reverse order. Value semantics let you reason about pricing functions as pure mathematics — no aliasing surprises corrupting a Monte Carlo path. Choosing stack over heap keeps your inner pricing loop free of allocator calls, which is often the difference between meeting and missing a latency budget. These foundations are why production risk engines are overwhelmingly written in C++ rather than garbage-collected languages where finalization timing is non-deterministic.

Adapted from Stroustrup — The C++ Programming Language; Joshi — C++ Design Patterns and Derivatives Pricing.