diff --git a/org/cpp/arrays-and-refs.org b/org/cpp/arrays-and-refs.org new file mode 100644 index 0000000..26dd16d --- /dev/null +++ b/org/cpp/arrays-and-refs.org @@ -0,0 +1,120 @@ +* Why can't you return a raw C-style array :cpp:arrays:elaborative-why: +:PROPERTIES: +:ANKI_NOTE_TYPE: Basic +:END: +** Front +Why is returning a raw C-style array illegal in C++? +** Back +Arrays /decay to pointers/ when passed around. Returning one would return a pointer to a local variable that's destroyed when the function returns — undefined behavior. The compiler forbids it. + +#+begin_src c++ +int arr[26]; +return arr; // ❌ returns pointer to dead stack memory +#+end_src + +* std::array vs int[]: key differences :cpp:arrays:comparative: +:PROPERTIES: +:ANKI_NOTE_TYPE: Basic +:END: +** Front +How does ~std::array~ differ from ~int[26]~? +** Back +| Feature | ~int[26]~ | ~std::array~ | +|----------------------+-----------+---------------------| +| Return by value | No | Yes | +| Copy/assign | No | Yes | +| Knows its own size | No | ~.size()~ | +| Works with STL algos | No | Yes | +| Zero-init with ~{}~ | No | Yes | + +Same machine code — zero overhead. + +* Task: return character frequency count from string :cpp:arrays:production: +:PROPERTIES: +:ANKI_NOTE_TYPE: Basic +:END: +** Front +Write a function that counts character frequencies in a string and returns the result. The string has only lowercase letters. +** Back +#+begin_src c++ +std::array calc(const std::string& str) { + std::array arr{}; + for (char c : str) { + arr[c - 'a']++; + } + return arr; +} +#+end_src + +* Stack vs heap: std::array vs std::vector :cpp:arrays:comparative: +:PROPERTIES: +:ANKI_NOTE_TYPE: Basic +:END: +** Front +Where is the data stored for ~std::array~ vs ~std::vector(26)~? +** Back +- ~std::array~ → *stack*. Data stored inline inside the struct, no dynamic allocation. +- ~std::vector~ → *heap*. Internally calls ~new[]~, pointer indirection. + +Rule: use ~std::array~ when size is known at compile time (fast, no alloc). Use ~std::vector~ when size is dynamic. + +* Why const in const T& parameter :cpp:references:elaborative-why: +:PROPERTIES: +:ANKI_NOTE_TYPE: Basic +:END: +** Front +Why write ~const std::string&~ instead of ~std::string&~ for a read-only parameter? +** Back +Two reasons: + +1. *Enforces intent* — compiler catches accidental mutation inside the function. +2. *Allows more callers* — without ~const~, you can't pass temporaries or const variables: + +#+begin_src c++ +calc("hello"); // ❌ without const +const std::string s = "hi"; +calc(s); // ❌ without const +#+end_src + +* Why & instead of pass-by-value for string param :cpp:references:elaborative-why: +:PROPERTIES: +:ANKI_NOTE_TYPE: Basic +:END: +** Front +Why pass ~std::string~ by reference (~const std::string&~) instead of by value? +** Back +~std::string~ contains a heap allocation. Passing by value copies it — allocating memory and copying every character. + +#+begin_src c++ +calc(std::string str) // copies entire string — heap allocation +calc(const std::string& str) // passes address only — no copy +#+end_src + +For a function that only reads, the copy is pure waste. + +* Reference vs pointer for function parameters :cpp:references:comparative: +:PROPERTIES: +:ANKI_NOTE_TYPE: Basic +:END: +** Front +When do you use ~T&~ vs ~T*~ for a function parameter? +** Back +| Feature | Reference ~T&~ | Pointer ~T*~ | +|-------------------+----------------+--------------------| +| Can be null | No | Yes | +| Dereference | ~str[i]~ | ~(*str)[i]~ | +| Can be reassigned | No | Yes | + +Use ~T*~ when null is a valid input. Use ~T&~ when the value is *guaranteed to exist* — which is almost always the case for function parameters. + +* Rule of thumb: C++ function parameter types :cpp:references:factual: +:PROPERTIES: +:ANKI_NOTE_TYPE: Basic +:END: +** Front +What's the general rule for choosing parameter types in C++ functions? +** Back +- *Non-trivial types* (~string~, ~vector~, structs): use ~const T&~ for read-only, ~T&~ for mutating +- *Cheap types* (~int~, ~char~, ~bool~, pointers): pass by value +- *Nullable input*: use ~T*~ +- *Guaranteed non-null*: use ~T&~