C++ · Reference notes
C++ Complete Notes
Compiled from beginner C++ video courses (Bro Code style + Dave/Mike style tutorials)
Table of Contents
- Getting Started
- Your First Program
- Variables & Data Types
- Constants
- Namespaces
- Type Aliases (typedef / using)
- Operators
- Type Conversion
- User Input
- Math Functions
- Strings
- Control Flow: if / else
- Switch Statements
- Ternary Operator
- Logical Operators
- Loops
- Break & Continue
- Arrays
- Multidimensional Arrays
- Functions
- Return Keyword
- Overloaded Functions
- Variable Scope
- Random Numbers
- Memory Addresses & Pointers
- Pass by Value vs Pass by Reference
- Const Parameters
- Dynamic Memory
- Recursion
- Function Templates
- Structs
- Enums
- Object-Oriented Programming
- Constructors
- Object (Member) Functions
- Getters & Setters
- Inheritance
- Mini Practice Projects
Getting Started
C++ is a fast, middle-level language — closely related to C. It's used in graphics-intensive applications, video editing software, embedded systems, and video games. It sits between low-level languages (close to hardware) and high-level languages (like Python/Java, easier to read but slower).
What You Need
- A text editor / IDE — e.g. VS Code, Code::Blocks, Notepad++. Code::Blocks bundles the compiler too, which is convenient for beginners.
- A compiler — translates C++ source code into machine instructions.
- Windows/Linux → GCC (MinGW on Windows)
- Mac → Clang (or run
xcode-select --installin Terminal, then check withgcc -v)
Basic Workflow
- Build = convert your code into machine-understandable instructions.
- Run = execute those instructions.
- File extension:
.cpp
#include <iostream>
using namespace std;
int main() {
cout << "Hello World" << endl;
return 0;
}#include <iostream>— imports the input/output library.using namespace std;— lets you skip typingstd::before things likecout.int main() { ... }— the entry point of every C++ program; code inside runs top to bottom.return 0;— signals the program ended without errors (non-zero = a problem occurred).
Your First Program
#include <iostream>
int main() {
std::cout << "I like pizza" << std::endl; // end line, flushes buffer
std::cout << "It's really good" << "\n"; // '\n' = new line char (faster, no flush)
// This is a single-line comment
/* This is a
multi-line comment */
return 0;
}std::cout <<— character output ("standard character output").<<is the insertion/left-shift operator.endlvs\n— both create new lines;endlalso flushes the output buffer (slightly slower),\nis a plain newline character.- Every statement ends with a semicolon
;.
Variables & Data Types
A variable is a named container for a value stored in memory. Two steps: declaration (naming + typing it) and assignment (giving it a value). You can do both at once.
int x; // declaration
x = 5; // assignment
int y = 6; // declaration + assignment in one lineCommon Primitive Types
| Type | Stores | Example |
|---|---|---|
int | Whole number | int age = 21; |
double | Number with decimal (more precision) | double price = 10.99; |
float | Number with decimal (less precision) | float temp = 98.6f; |
char | A single character (single quotes) | char grade = 'A'; |
bool | true or false | bool isStudent = true; |
std::string | A sequence of text (double quotes) | string name = "Bro Code"; |
Notes:
- If you assign a decimal to an
int, the decimal part is truncated (not rounded):int days = 7.5;→daysbecomes7. charcan only hold ONE character — assigning more causes overflow and only the last character is kept.doubleallows more decimal precision thanfloat.- You can print text + variables together:
cout << "Hello " << name << endl;
cout << "You are " << age << " years old" << endl;- A value typed directly (not stored in a variable) is called a constant/literal, e.g.
cout << 4.5;.
Constants
The const keyword makes a variable read-only — the compiler prevents any modification after initialization.
const double PI = 3.14159; // convention: ALL_CAPS for constants
double radius = 10;
double circumference = 2 * PI * radius;Trying to reassign PI later causes a compile error ("assignment of read-only variable"). Use const any time a value should never change (physical constants, screen dimensions, etc.).
Namespaces
A namespace prevents naming conflicts by grouping identically-named entities separately.
namespace first { int x = 1; }
namespace second { int x = 2; }
int x = 0; // global/local x
cout << x; // 0 (local version)
cout << first::x; // 1 (scope resolution operator ::)
cout << second::x; // 2
using namespace first; // now "x" without prefix refers to first::xusing namespace std;avoids typingstd::everywhere, but with large programs it increases the chance of naming collisions.- Safer alternative:
using std::cout;(only import what you need).
Type Aliases
typedef (older) and using (modern, preferred — works better with templates) create a nickname for an existing data type.
typedef std::string text_t;
text_t firstName = "Bro";
using number_t = int;
number_t age = 21;Common naming convention: alias name ends in _t. Use aliases only when there's a clear readability benefit (e.g. shortening a long templated type like std::vector<std::pair<std::string,int>>).
Operators
Arithmetic Operators
| Operator | Meaning | Shorthand |
|---|---|---|
+ | Addition | x += 1; |
- | Subtraction | x -= 1; |
* | Multiplication | x *= 2; |
/ | Division | x /= 2; |
% | Modulus (remainder) | — |
++ | Increment by 1 | x++; |
-- | Decrement by 1 | x--; |
int students = 20;
students++; // 21 (preferred way to add 1)
int remainder = students % 3; // remainder of division — great for checking even/odd- Integer division between two
ints discards the decimal (10 / 3→3). Cast at least one operand todoubleto keep the decimal:10 / 3.0→3.333.... - Order of operations follows standard math rules: parentheses → multiplication/division → addition/subtraction. Use
()to force a different order.
Comparison Operators
== (equal), != (not equal), >, <, >=, <= — each evaluates to a bool (true/false).
Type Conversion
Implicit conversion happens automatically (e.g. assigning 3.14 to an int truncates it to 3).
Explicit conversion (casting): put the target type in parentheses before the value.
int x = (int)3.14; // explicit cast → 3
double score = (double)correct / questions * 100; // avoids integer-division bugUser Input
string name;
cout << "What's your name? ";
cin >> name; // stops reading at first whitespace!
int age;
cout << "What's your age? ";
cin >> age;
// For strings that may contain spaces, use getline:
string fullName;
cout << "What's your full name? ";
cin >> ws; // eats leftover newline/whitespace in the buffer
getline(cin, fullName);cin >>(extraction operator, two right angle brackets) reads a single token (int, char, or word — no spaces).getline(cin, variable)reads an entire line, including spaces.- Mixing
cin >>thengetlinecan cause the getline to grab a leftover newline — fix withcin >> wsbefore the getline. cin.clear();andcin.ignore()/cin.sync()help reset the input buffer after invalid input (e.g. clear error flags then flush the stream).
Math Functions
Requires #include <cmath>.
std::max(x, y); std::min(x, y);
pow(base, exponent);
sqrt(x);
abs(x);
round(x); ceil(x); floor(x);round()rounds normally,ceil()always rounds up,floor()always rounds down.srand(time(0));seeds the pseudo-random number generator (needs#include <ctime>);rand()then generates a number 0 toRAND_MAX.- To get a random number in a range:
rand() % range + minValue(e.g.rand() % 6 + 1for a 6-sided die).
Strings
#include <string> (usually already available via <iostream> + using namespace std;).
| Method | Effect |
|---|---|
str.length() | number of characters |
str.empty() | true if string has no characters |
str.clear() | erases all contents |
str.append("text") | adds text to the end |
str[i] | access character at index i (0-based) |
str.insert(i, "text") | inserts text at position i |
str.find("x") | index of first occurrence (or string::npos if not found) |
str.erase(start, count) | removes count characters starting at start |
str.substr(start, len) | extracts a substring |
string phrase = "draft Academy";
cout << phrase.length(); // 15 (index starts at 0)
cout << phrase[0]; // 'd'
phrase[0] = 'b'; // modify a single character
cout << phrase.find("Academy"); // 8
cout << phrase.substr(8, 3); // "Aca"Concatenating a string with a variable inline:
cout << "Hello " << name << ", you are " << age << " years old" << endl;Control Flow: if / else
int age;
cin >> age;
if (age >= 18) {
cout << "Welcome to the site" << endl;
} else if (age < 0) {
cout << "You haven't been born yet" << endl;
} else if (age >= 100) {
cout << "You are too old to enter this site" << endl;
} else {
cout << "You are not old enough to enter" << endl;
}- Conditions are checked top to bottom; order matters (more specific conditions should come first).
- Comparison inside
if()resolves to abool— you can also just write aboolvariable directly:if (isStudent) { ... }. - Use
!(negation/NOT) to flip a condition:if (!isRaining) { ... }.
Switch Statements
An efficient alternative to a long chain of else if statements when comparing ONE value against MANY specific values.
switch (month) {
case 1:
cout << "January";
break;
case 2:
cout << "February";
break;
default:
cout << "Invalid month";
break;
}- Always
break;at the end of each case, or execution "falls through" to the next case. default:runs when no case matches (likeelse).- Only works with integral types,
char, andenumvalues — notstring(unless you convert to anenumor comparecharbychar).
Ternary Operator
Shorthand replacement for a simple if/else: condition ? valueIfTrue : valueIfFalse
string result = (grade >= 60) ? "You pass" : "You fail";
cout << (number % 2 == 1 ? "odd" : "even");
cout << (isHungry ? "You are hungry" : "You are full");Logical Operators
| Operator | Meaning | Example |
|---|---|---|
&& | AND — both conditions must be true | if (temp > 0 && temp < 30) |
|| | OR — at least one condition must be true | if (temp <= 0 || temp >= 30) |
! | NOT — reverses true/false | if (!isSunny) |
Loops
While Loop
Checks the condition before each iteration.
int index = 1;
while (index <= 5) {
cout << index << endl;
index++;
}⚠️ Forgetting to update the loop variable creates an infinite loop.
Do-While Loop
Runs the body once first, then checks the condition — guarantees at least one execution.
int number;
do {
cout << "Enter a positive number: ";
cin >> number;
} while (number < 0);For Loop
Best when you know how many times to loop. Structure: for (init; condition; update)
for (int i = 1; i <= 10; i++) {
cout << i << " ";
}- Can count by any step:
i += 2, or count down:for (int i = 10; i >= 0; i--). - For-each loop — simplified syntax for iterating a full collection (less flexible, but concise):
for (string student : students) {
cout << student << endl;
}Nested Loops
A loop inside another loop — useful for grids, 2D data, and multiplication tables.
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= columns; j++) {
cout << symbol;
}
cout << endl;
}Break & Continue
break;— exits the loop (or switch) immediately.continue;— skips the rest of the current iteration and moves to the next one.
for (int i = 1; i <= 20; i++) {
if (i == 13) continue; // skips printing 13, keeps going
cout << i << " ";
}Arrays
A container that holds multiple values of the same data type, accessed by index (starting at 0).
string cars[] = {"Corvette", "Mustang", "Camry"};
cout << cars[0]; // "Corvette"
cars[0] = "Camaro"; // reassign an element
int numbers[10]; // declare with a fixed size, assign values later
numbers[0] = 100;- Arrays are a static data structure — size is fixed once declared.
sizeof(array) / sizeof(array[0])calculates the number of elements.- Iterate with a standard
forloop or afor-eachloop. - Passing an array to a function: only pass the array name (no brackets); the array decays into a pointer, so the function loses knowledge of its size — pass the size as a separate argument too.
double getTotal(double prices[], int size) {
double total = 0;
for (int i = 0; i < size; i++) total += prices[i];
return total;
}- Linear search: loop through every element checking for a match; return the index, or
-1(a common "not found" sentinel value) if nothing matches. - Bubble sort: repeatedly compare adjacent elements and swap them if out of order; larger values "bubble" toward the end.
fill(arr, arr + size, value)(from<algorithm>) fills a range of elements with one value.
Multidimensional Arrays
An array where each element is itself another array — great for grids/matrices (rows & columns).
string cars[3][3] = {
{"Mustang", "Escape", "F150"},
{"Corvette", "Equinox", "Silverado"},
{"Challenger", "Durango", "Ram1500"}
};
cout << cars[0][0]; // "Mustang" (row 0, column 0)Iterate with nested for loops — outer loop for rows, inner loop for columns:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
cout << cars[i][j] << " ";
}
cout << endl;
}Functions
A function is a reusable block of code that performs a specific task — write once, call many times.
void sayHi(string name, int age) { // declaration/definition
cout << "Hello " << name << ", you are " << age << endl;
}
int main() {
sayHi("Mike", 60); // call/invoke — pass arguments
return 0;
}void= the function returns nothing.- Parameters are the placeholders in the function definition; arguments are the actual values passed when calling.
- Functions can't see each other's local variables — pass what's needed as arguments.
- If a function is defined after
main(), add a function declaration (prototype) abovemain()so the compiler knows about it in advance:
void sayHi(string name, int age); // prototypeReturn Keyword
return sends a value back to wherever the function was called, and immediately exits the function.
double square(double length) {
return length * length;
}
double area = square(6.0); // 36- The function's return type (before the function name) must match the type of value returned (
voidif nothing is returned). - Any code after a
returnstatement inside that path never executes.
Overloaded Functions
Multiple functions can share the same name as long as they have a different set of parameters (a different "function signature").
void bakePizza() { cout << "Here is your pizza"; }
void bakePizza(string topping) { cout << "Here is your " << topping << " pizza"; }
void bakePizza(string t1, string t2) { cout << "Here is your " << t1 << " and " << t2 << " pizza"; }The compiler picks the correct version based on how many/what type of arguments you pass.
Variable Scope
- Local variables — declared inside a function or
{ }block; only visible there. Different functions can reuse the same variable name safely. - Global variables — declared outside all functions (top of file); accessible everywhere. Generally avoid globals — they pollute the namespace and are less secure/predictable.
- A local variable takes priority over a global one with the same name. Use the scope resolution operator
::variableNameto explicitly access the global version.
Random Numbers
#include <cstdlib>
#include <ctime>
srand(time(0)); // seed once (usually at program start)
int diceRoll = rand() % 6 + 1; // random number 1–6rand() % N gives 0 to N-1; add 1 (or a minimum value) to shift the range as needed.
Memory Addresses & Pointers
Every variable lives at a physical memory address in RAM. The address-of operator & retrieves that address.
int age = 21;
cout << &age; // prints a hexadecimal memory addressA pointer is a variable that stores a memory address (instead of a normal value). Declared using the same data type as what it points to, plus *.
int age = 21;
int* pAge = &age; // pAge holds the ADDRESS of age
cout << pAge; // prints the address
cout << *pAge; // DEREFERENCE: prints the VALUE at that address (21)&variable→ get the address (creates a pointer).*pointer→ dereference: get the value stored at that address.- Arrays are already addresses — you don't need
&when pointing to one. - A null pointer (
nullptr) points to nothing. Good practice: initialize pointers tonullptrif you're not assigning them right away, and checkif (ptr != nullptr)before dereferencing to avoid undefined behavior.
Pass by Value vs Pass by Reference
- Pass by value (default): the function receives a copy of the argument — modifying it inside the function does NOT affect the original.
- Pass by reference: prefix the parameter with
&— the function works with the actual original variable/memory address, so changes persist outside the function.
void swap(string &x, string &y) { // pass by reference
string temp = x;
x = y;
y = temp;
}Use pass by reference whenever a function needs to modify the caller's original variable (e.g., swap functions), and generally prefer it for efficiency with large objects (avoids copying).
Const Parameters
Adding const before a parameter makes it read-only inside the function — the compiler blocks any attempt to modify it. Improves safety and communicates intent to other developers (especially important when combined with references/pointers, where an accidental modification would otherwise affect the original data).
void printInfo(const string &name, const int &age) {
// name and age cannot be reassigned in here
}Dynamic Memory
Memory allocated while the program is running (in the heap, not the fixed-size stack) — useful when you don't know how much storage you'll need in advance (e.g., depends on user input).
int* pNum = nullptr;
pNum = new int; // allocate space for one int in the heap
*pNum = 21;
delete pNum; // free the memory when done (prevents memory leaks)
// Dynamic array:
int size;
cin >> size;
char* pGrades = new char[size];
// ... use pGrades[i] ...
delete[] pGrades; // note the [] when deleting an arrayRule of thumb: every new should eventually be matched with a delete (or delete[] for arrays) to avoid memory leaks.
Recursion
A function that calls itself to break a problem into smaller repeatable steps. Requires a base case to stop, or you'll get infinite recursion → stack overflow.
int factorial(int num) {
if (num > 1) {
return num * factorial(num - 1); // recursive case
} else {
return 1; // base case
}
}- Pros: often cleaner/easier to read for problems like tree traversal, sorting/searching algorithms.
- Cons: uses more memory and is generally slower than an equivalent iterative (loop-based) solution.
Function Templates
A template lets you write one function that works with multiple data types, avoiding duplicate overloaded functions.
template <typename T>
T getMax(T x, T y) {
return (x > y) ? x : y;
}
getMax(1, 2); // works with int
getMax(1.1, 2.1); // works with double
getMax('a', 'b'); // works with charFor mixing two different types, add a second template parameter and use auto as the return type so the compiler deduces the correct one:
template <typename T, typename U>
auto getMax(T x, U y) {
return (x > y) ? x : y;
}Structs
A struct groups related variables of different data types under one name (unlike arrays, which only hold one data type).
struct Student {
string name;
double gpa;
bool enrolled = true; // members can have default values
};
Student student1;
student1.name = "SpongeBob";
student1.gpa = 3.2;
cout << student1.name;- Members are accessed with the dot operator
.. - Structs are passed by value by default (a copy is made) — use
&in the parameter to pass by reference if you need to modify the original.
void printCar(Car &car) { cout << car.model; } // pass by referenceEnums
enum (enumeration) is a user-defined type made of paired names and integer constants — great for representing a fixed set of options (and usable inside switch statements, unlike string).
enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY };
// If you don't assign values explicitly, they default to 0, 1, 2, 3...
Day today = FRIDAY;
switch (today) {
case SUNDAY: cout << "It is Sunday"; break;
case FRIDAY: cout << "It is Friday"; break;
// ...
}An enum variable can only take one value from its defined set.
Object-Oriented Programming
An object is a collection of:
- Attributes (characteristics / data) — e.g. a phone has a version, charge level.
- Methods (functions / actions it can perform) — e.g. a phone can make calls, play games.
A class is the blueprint used to create objects. An object is an actual instance of that blueprint.
class Human {
public:
string name;
string occupation;
int age;
void eat() { cout << "This person is eating"; }
void drink() { cout << "This person is drinking"; }
void sleep() { cout << "This person is sleeping"; }
};
Human human1;
human1.name = "Rick";
human1.occupation = "Scientist";
human1.age = 70;
human1.eat(); // invoke a methodpublic:access modifier makes members accessible from outside the class.- You can create as many objects from one class as you like — each has its own independent copy of the attributes.
Constructors
A constructor is a special method (same name as the class, no return type) that runs automatically whenever an object is created — perfect for initializing attributes from arguments instead of assigning them manually one by one.
class Student {
public:
string name;
int age;
double gpa;
Student(string name, int age, double gpa) {
this->name = name; // "this" refers to the current object
this->age = age;
this->gpa = gpa;
}
};
Student student1("SpongeBob", 25, 3.2); // constructor called automaticallythis->attributedisambiguates the class member from a same-named parameter.- Overloaded constructors: define multiple constructors with different parameter lists to allow flexible object creation (e.g., a pizza with 0, 1, or 2 toppings).
Pizza() {} // no-topping constructor
Pizza(string topping1) { ... } // one topping
Pizza(string topping1, string topping2) { ... } // two toppingsObject (Member) Functions
Functions defined inside a class that operate on that object's own data — great for computing derived information or performing an action using the object's attributes.
class Student {
public:
double gpa;
bool hasHonors() {
if (gpa >= 3.5) return true;
else return false;
}
};
student1.hasHonors(); // uses student1's own gpa valueChanging the logic in one place (e.g. the honors GPA threshold) automatically updates behavior for every object of that class — a key benefit of OOP.
Getters & Setters
Used for abstraction/encapsulation — hiding internal data from direct outside access using private, and exposing controlled access through public methods.
class Movie {
private:
string rating; // hidden from outside code
public:
void setRating(string r) {
if (r == "G" || r == "PG" || r == "PG13" || r == "R" || r == "NR") {
rating = r;
} else {
rating = "NR"; // reject invalid input, default safely
}
}
string getRating() { return rating; }
};
Movie avengers;
avengers.setRating("PG13"); // must go through the setter
cout << avengers.getRating(); // must go through the getter- Getter: makes a private attribute readable.
- Setter: makes a private attribute writable — and lets you add validation logic before allowing the change.
publicmembers are accessible from anywhere;privatemembers are only accessible from within the class itself.- Constructors can call setters internally to reuse validation logic.
Inheritance
A class (child/subclass) can inherit attributes and methods from another class (parent/superclass) — promotes code reuse and avoids repetition.
class Animal {
public:
bool alive = true;
void eat() { cout << "This animal is eating"; }
};
class Dog : public Animal { // Dog inherits from Animal
public:
void bark() { cout << "The dog goes woof"; }
};
Dog myDog;
myDog.eat(); // inherited from Animal
myDog.bark(); // defined in Dog- Syntax:
class Child : public Parent { ... }; - A subclass can add new members and override an inherited method by redefining it with the same signature.
- If multiple classes share common attributes/methods, put them in a shared parent class so you only maintain that logic in one place.
Mini Practice Projects
(Referenced throughout the courses — good exercises to build once you know the fundamentals)
- Hypotenuse calculator (math functions + user input)
- Simple console calculator (switch statement)
- Temperature converter (Celsius ⇄ Fahrenheit)
- Number guessing game (do-while loop, random numbers)
- Random event/prize generator (switch + random numbers)
- Rock, Paper, Scissors game (functions, switch, random numbers)
- Quiz game (2D arrays, arrays, scoring)
- Credit card validator (Luhn algorithm — string/array manipulation)
- Banking program (deposit/withdraw/balance — functions, do-while, validation)
- Tic-Tac-Toe (pointers, arrays, win-condition checks, random computer moves)
- Mad Libs generator (string input, string concatenation)
- Basic 4-function calculator (if/else chains for operator selection)
Quick Reference Cheat Sheet
#include <iostream>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
// Variables
int age = 21;
double gpa = 3.5;
char grade = 'A';
bool isStudent = true;
string name = "Bro";
// Output / Input
cout << "Hello " << name << endl;
cin >> age;
getline(cin, name);
// Conditionals
if (age >= 18) { /* ... */ }
else { /* ... */ }
// Loop
for (int i = 0; i < 10; i++) { /* ... */ }
// Array
int nums[5] = {1, 2, 3, 4, 5};
// Function
// int add(int a, int b) { return a + b; }
return 0;
}End of notes.


