Module 01: Memory Allocation, References, and Pointers
Key Concepts:
- Stack vs Heap allocation
newanddeleteoperators- References vs Pointers
- Pointers to members
switchstatements
1. Stack vs Heap Memory
Section titled “1. Stack vs Heap Memory”Stack Allocation (Automatic)
Section titled “Stack Allocation (Automatic)”void function() { int x = 42; // On stack Zombie zombie; // On stack} // Automatically destroyed hereCharacteristics:
- Fast allocation/deallocation
- Limited size (~1-8 MB typically)
- Automatic cleanup when scope ends
- Cannot outlive function
Heap Allocation (Dynamic)
Section titled “Heap Allocation (Dynamic)”void function() { int* x = new int(42); // On heap Zombie* zombie = new Zombie(); // On heap
// ... use them ...
delete x; // Must manually delete delete zombie; // Must manually delete}Characteristics:
- Slower allocation
- Large capacity (limited by RAM)
- Must be manually freed
- Can outlive function (return pointer)
2. new and delete Operators
Section titled “2. new and delete Operators”Single Object
Section titled “Single Object”// Allocationint* ptr = new int; // Uninitializedint* ptr = new int(); // Zero-initializedint* ptr = new int(42); // Initialized to 42
// Deallocationdelete ptr;ptr = NULL; // Good practice (C++98)Arrays
Section titled “Arrays”// Allocationint* arr = new int[10]; // Array of 10 intsZombie* horde = new Zombie[5]; // Array of 5 Zombies
// Deallocation - NOTE THE []delete[] arr; // MUST use delete[] for arraysdelete[] horde;Common Mistakes
Section titled “Common Mistakes”// WRONG: Using delete on arrayint* arr = new int[10];delete arr; // UNDEFINED BEHAVIOR!
// WRONG: Using delete[] on single objectint* ptr = new int(42);delete[] ptr; // UNDEFINED BEHAVIOR!
// WRONG: Double deleteint* ptr = new int(42);delete ptr;delete ptr; // CRASH or corruption!When to Use Stack vs Heap
Section titled “When to Use Stack vs Heap”| Use Stack When… | Use Heap When… |
|---|---|
| Object’s lifetime = function scope | Object must outlive function |
| Size known at compile time | Size determined at runtime |
| Small objects | Large objects |
| Performance critical | Returning new objects |
3. References
Section titled “3. References”What is a Reference?
Section titled “What is a Reference?”A reference is an alias - another name for an existing variable.
int x = 42;int& ref = x; // ref IS x (not a copy, not a pointer)
ref = 100; // Changes x to 100std::cout << x; // Prints 100References vs Pointers
Section titled “References vs Pointers”| Feature | Reference | Pointer |
|---|---|---|
| Syntax | int& ref = x; | int* ptr = &x; |
| Can be null | No | Yes |
| Can be reassigned | No | Yes |
| Must be initialized | Yes | No |
| Access value | ref | *ptr |
| Access address | &ref | ptr |
Key Rules for References
Section titled “Key Rules for References”// MUST initializeint& ref; // ERROR: references must be initializedint& ref = x; // OK
// CANNOT be nullint& ref = NULL; // ERROR: cannot bind to null
// CANNOT be reassignedint& ref = x;ref = y; // This doesn't reassign ref, it copies y to x!Why References Exist
Section titled “Why References Exist”// BAD: Passing by value (copies entire object)void printZombie(Zombie z) { // z is a COPY - expensive for large objects}
// BETTER: Passing by pointervoid printZombie(Zombie* z) { if (z != NULL) // Must check for null std::cout << z->getName();}
// BEST: Passing by referencevoid printZombie(Zombie& z) { // z is the original object - no copy // Cannot be null - no check needed std::cout << z.getName();}
// CONST reference - read-only accessvoid printZombie(const Zombie& z) { std::cout << z.getName(); // Can read // z.setName("X"); // ERROR: z is const}When to Use What
Section titled “When to Use What”| Situation | Use |
|---|---|
| Never null, won’t change what it refers to | Reference |
| Might be null | Pointer |
| Needs to be reassigned | Pointer |
| Return new object from function | Pointer (or smart pointer in modern C++) |
| Optional parameter | Pointer (can pass NULL) |
4. Memory Address Demonstration (ex02)
Section titled “4. Memory Address Demonstration (ex02)”std::string str = "HI THIS IS BRAIN";std::string* stringPTR = &str; // Pointer TO strstd::string& stringREF = str; // Reference (alias) OF str
// Addresses - all should be the same!std::cout << &str << std::endl; // Address of strstd::cout << stringPTR << std::endl; // Pointer holds same addressstd::cout << &stringREF << std::endl; // Address of ref = address of str
// Values - all should be the same!std::cout << str << std::endl; // Direct accessstd::cout << *stringPTR << std::endl; // Dereference pointerstd::cout << stringREF << std::endl; // Reference is same as original5. Reference vs Pointer in Classes (ex03)
Section titled “5. Reference vs Pointer in Classes (ex03)”Using a Reference (HumanA)
Section titled “Using a Reference (HumanA)”class HumanA {private: std::string _name; Weapon& _weapon; // Reference - MUST always have a weapon
public: // MUST initialize reference in constructor HumanA(std::string name, Weapon& weapon) : _name(name), _weapon(weapon) {}
void attack() { std::cout << _name << " attacks with " << _weapon.getType(); }};
// UsageWeapon club("club");HumanA bob("Bob", club); // MUST provide weapon at constructionUsing a Pointer (HumanB)
Section titled “Using a Pointer (HumanB)”class HumanB {private: std::string _name; Weapon* _weapon; // Pointer - might not have a weapon
public: HumanB(std::string name) : _name(name), _weapon(NULL) {}
void setWeapon(Weapon& weapon) { _weapon = &weapon; }
void attack() { if (_weapon) std::cout << _name << " attacks with " << _weapon->getType(); else std::cout << _name << " has no weapon"; }};
// UsageHumanB jim("Jim"); // No weapon initiallyjim.setWeapon(club); // Weapon added laterDecision Guide
Section titled “Decision Guide”- Reference: When object MUST exist at construction and throughout lifetime
- Pointer: When object might not exist, or might change
6. Pointers to Members (ex05)
Section titled “6. Pointers to Members (ex05)”Function Pointers (C-style)
Section titled “Function Pointers (C-style)”void sayHello() { std::cout << "Hello"; }void sayBye() { std::cout << "Bye"; }
// Function pointervoid (*funcPtr)() = &sayHello;funcPtr(); // Calls sayHello()
funcPtr = &sayBye;funcPtr(); // Calls sayBye()Pointers to Member Functions
Section titled “Pointers to Member Functions”class Harl {public: void debug() { std::cout << "Debug"; } void info() { std::cout << "Info"; } void warning() { std::cout << "Warning"; } void error() { std::cout << "Error"; }
void complain(std::string level) { // Array of member function pointers void (Harl::*funcs[4])() = { &Harl::debug, &Harl::info, &Harl::warning, &Harl::error };
std::string levels[4] = {"DEBUG", "INFO", "WARNING", "ERROR"};
for (int i = 0; i < 4; i++) { if (level == levels[i]) { (this->*funcs[i])(); // Call the member function return; } } }};Syntax Breakdown
Section titled “Syntax Breakdown”// Declarationvoid (ClassName::*pointerName)(parameters);
// AssignmentpointerName = &ClassName::methodName;
// Call via object(object.*pointerName)(args);
// Call via pointer to object(objectPtr->*pointerName)(args);7. switch Statement (ex06)
Section titled “7. switch Statement (ex06)”Basic Syntax
Section titled “Basic Syntax”switch (expression) { case value1: // code break; case value2: // code break; default: // code if no match}Fall-through Behavior
Section titled “Fall-through Behavior”// WITHOUT break - falls through to next caseswitch (level) { case 3: // WARNING std::cout << "Warning message\n"; // No break - falls through! case 2: // INFO std::cout << "Info message\n"; // No break - falls through! case 1: // DEBUG std::cout << "Debug message\n"; break;}
// If level = 3: prints Warning, Info, Debug// If level = 2: prints Info, Debug// If level = 1: prints Debugswitch vs if-else
Section titled “switch vs if-else”// Can only switch on integral types in C++98switch (number) { ... } // OKswitch (character) { ... } // OKswitch (string) { ... } // ERROR in C++98!
// For strings, must use if-elseif (str == "DEBUG") { ... }else if (str == "INFO") { ... }String-to-Integer Conversion for Switch
Section titled “String-to-Integer Conversion for Switch”Since C++98 cannot switch on strings, convert strings to integers first:
// Convert string to index for switchint getLevel(const std::string& level) { std::string levels[4] = {"DEBUG", "INFO", "WARNING", "ERROR"}; for (int i = 0; i < 4; i++) { if (level == levels[i]) return i; } return -1; // Not found}
void complain(const std::string& level) { switch (getLevel(level)) { case 0: std::cout << "Debug message" << std::endl; break; case 1: std::cout << "Info message" << std::endl; break; case 2: std::cout << "Warning message" << std::endl; break; case 3: std::cout << "Error message" << std::endl; break; default: std::cout << "Unknown level" << std::endl; }}This is cleaner than a long if-else chain and allows fall-through behavior.
8. File I/O (ex04)
Section titled “8. File I/O (ex04)”Reading from File
Section titled “Reading from File”#include <fstream>#include <string>
std::ifstream inFile("input.txt");
if (!inFile.is_open()) { std::cerr << "Cannot open file" << std::endl; return 1;}
std::string line;while (std::getline(inFile, line)) { std::cout << line << std::endl;}
inFile.close();Writing to File
Section titled “Writing to File”std::ofstream outFile("output.txt");
if (!outFile.is_open()) { std::cerr << "Cannot create file" << std::endl; return 1;}
outFile << "Hello, World!" << std::endl;outFile << "Line 2" << std::endl;
outFile.close();Reading Entire File into String
Section titled “Reading Entire File into String”std::ifstream inFile("input.txt");std::string content;std::string line;
while (std::getline(inFile, line)) { content += line; content += "\n";}Quick Reference
Section titled “Quick Reference”Memory
Section titled “Memory”// Single objectType* ptr = new Type(args);delete ptr;
// ArrayType* arr = new Type[size];delete[] arr;References
Section titled “References”Type& ref = original; // Create alias// ref is now indistinguishable from originalMember Function Pointers
Section titled “Member Function Pointers”void (Class::*ptr)(args) = &Class::method;(object.*ptr)(args);File I/O
Section titled “File I/O”std::ifstream in("file");std::ofstream out("file");std::getline(in, str);out << content;