Learn C++ learn from scratch with a complete tutorial covering setup, syntax, I/O, loops, functions, OOP, STL, files, templates, and a mini project.
1. Install & Setup (Windows / macOS / Linux)
Windows
- Install VS Code + the “C/C++” extension
- Install MinGW-w64 (provides
g++) - In Terminal:
g++ --version(should print a version)
macOS
- Run:
xcode-select --install - Install VS Code + C/C++ extension
- Check:
g++ --version
Ubuntu/Debian
sudo apt update
sudo apt install build-essential
g++ --version
2. Your First Program (Hello World)
#include <iostream> // (1)
using namespace std; // (2)
int main() { // (3)
cout << "Hello, World!\n"; // (4)
return 0; // (5)
}
How it works
- Loads the standard input/output library so
coutis available. - Lets you write
coutinstead ofstd::cout(convenience). - Program starts executing from
main(). It returns anintstatus to the OS. - Sends the string to standard output;
\nmoves the cursor to the next line. 0means “success”. (Non-zero usually signals an error.)
3. Program Structure Essentials
- Includes (
#include <...>) bring in libraries. - Namespaces avoid long names (e.g.,
std::cout). - main is the entry point.
- Return code (0 success, nonzero error).
4. Variables & Data Types
#include <iostream>
#include <string>
using namespace std;
int main() {
int age = 21; // (1)
double price = 999.99; // (2)
char grade = 'A'; // (3)
bool isPass = true; // (4)
const double PI = 3.14159; // (5)
string name = "Alice"; // (6)
cout << name << " " << age << " " << price << " " << grade << " " << isPass << "\n"; // (7)
}
How it works
intstores whole numbers.doublestores floating-point (decimal) numbers.charstores a single character (single quotes).boolstores logical values (true/false); printing shows1/0.constmakes the variable read-only (cannot change after initialization).stringholds text.- The stream insertion operator
<<chains multiple values to print in one line.
5. Operators & Expressions
- Arithmetic:
+ - * / % - Relational:
== != < > <= >= - Logical:
&& || ! - Increment/Decrement:
++a,a++,--a,a--
6. Input/Output (cin, cout, getline)
#include <iostream>
#include <string>
using namespace std;
int main() {
string fullName;
int year;
cout << "Enter your full name: ";
getline(cin, fullName); // (1)
cout << "Enter your birth year: ";
cin >> year; // (2)
cout << "Hi " << fullName << "! You were born in " << year << ".\n"; // (3)
}
How it works
getlinereads the entire line (including spaces) intofullName.cin >> yearreads the next “token” (stops at the first space/newline).- Concatenates the captured inputs and prints a friendly sentence.
Tip: If you mix
cin >>andgetlinein the other order, consume the leftover newline withcin.ignore()before callinggetline.
7. Control Flow (if/else, switch, loops)
if/else
int n;
cin >> n;
if (n % 2 == 0) cout << "Even\n";
else cout << "Odd\n";
How it works: % gets the remainder; even numbers give 0 when divided by 2.
switch
int op; cin >> op;
switch (op) {
case 1: cout << "Start\n"; break; // (a)
case 2: cout << "Stop\n"; break; // (b)
default: cout << "Invalid\n"; // (c)
}
How it works:
(a)(b) When a case matches, that block runs. break prevents falling into the next case.
(c) default runs if no case matches.
loops
for (int i=1; i<=5; i++) cout << i << " "; // (1) 1..5
int x=3; while (x>0) { cout << x-- << " "; } // (2) 3 2 1
int y=0; do { cout << y << " "; } while (++y<3); // (3) 0 1 2
How it works:
forhas initialization, condition, increment perfect for counted loops.whilerepeats while the condition stays true.do..whileruns the body once before checking the condition.
8. Functions (parameters, overloading, recursion)
int add(int a, int b) { return a + b; } // (A)
double add(double a, double b) { return a + b; } // (B)
long long fact(int n) { // (C)
if (n <= 1) return 1; // base case
return n * fact(n - 1); // recursive step
}
How it works
- (A) and (B) share the same name
addbut accept different types the compiler picks the correct one based on the arguments (this is function overloading). - (C)
factmultipliesnbyfact(n-1)until it hits the base casen <= 1, which returns 1 and stops further recursion.
9. Arrays, std::string, std::vector
int a[3] = {10,20,30}; // (1)
#include <vector>
vector<int> v = {1,2,3}; // (2)
v.push_back(4); // v = 1,2,3,4
#include <string>
string s = "Hello"; // (3)
s += " C++"; // "Hello C++"
How it works
- Raw array with fixed size (index from 0..2).
vectoris a dynamic array: grows/shrinks at runtime;push_backappends.stringsupports concatenation via+=.
10. Pointers & References
int x = 10;
int* p = &x; // (1)
*p = 20; // (2)
int y = 5;
int& r = y; // (3)
r = 7; // (4)
How it works
&xtakes the memory address ofx;pstores that address.*pdereferences the pointer (reaches intox) and changes its value to 20.ris a reference (an alias) toyit must refer to a valid object at initialization and cannot be reseated.- Assigning to
ractually assigns toy.
11. Dynamic Memory & Smart Pointers
Raw (manual avoid in new code):
int* p = new int(42); // (1)
cout << *p << "\n";
delete p; // (2)
How it works
newallocates aninton the heap and returns its address.deletefrees that memory; forgetting leads to memory leaks.
Modern approach
#include <memory>
auto up = std::make_unique<int>(42); // (A)
auto sp = std::make_shared<std::string>("Hi"); // (B)
How it works
- (A)
unique_ptrowns the object exclusively and deletes it automatically when it goes out of scope. - (B)
shared_ptrkeeps a reference count; when the last copy is destroyed, the object is freed.
12. Structs & Enums
struct Student {
std::string name;
int score;
};
enum class Color { Red, Green, Blue }; // strongly-typed enum
How it works
structgroups related fields.enum classavoids accidental conversions and name clashes.
13. OOP Classes, Constructors, Inheritance, Polymorphism
Classes & Inheritance
#include <iostream>
#include <string>
using namespace std;
class Person {
string name; // private
int age;
public:
Person(string n, int a): name(n), age(a) {} // ctor (init list)
void greet() const { cout << "Hi, I'm " << name << "\n"; }
};
class Employee : public Person { // inherits Person
double salary;
public:
Employee(string n,int a,double s): Person(n,a), salary(s) {}
void greet() const { cout << "Employee says hello!\n"; } // hides Person::greet
};
How it works
Personholds state (name,age) and behavior (greet). The constructor initializes members using an initializer list.EmployeeextendsPersonand addssalary. Itsgreethides the base method because the base method is notvirtual.
Polymorphism (runtime)
class Base {
public:
virtual void speak(){ cout << "Base\n"; } // (1)
};
class Der : public Base {
public:
void speak() override { cout << "Der\n"; } // (2)
};
Base* b = new Der(); // (3)
b->speak(); // prints "Der"
delete b;
How it works
virtualenables dynamic dispatch (decide the function at runtime by actual object type).overridetells the compiler we intend to override a virtual function.- A base pointer can point to a derived object; with
virtual, the derived method runs.
Safer modern style:
std::unique_ptr<Base> b = std::make_unique<Der>();(no manualdelete).
14. Exceptions (try/catch)
#include <iostream>
#include <stdexcept>
using namespace std;
double safeDiv(double a, double b){
if (b == 0) throw runtime_error("Divide by zero"); // (1)
return a / b;
}
int main(){
try { // (2)
cout << safeDiv(10, 0);
} catch (const exception& e) { // (3)
cerr << "Error: " << e.what() << "\n";
}
}
How it works
- Detect a problem and
throwan exception object with a message. - Put risky code in a
tryblock. catchhandles the error;e.what()prints the message.
15. Files & Streams (read/write)
#include <fstream>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main(){
ofstream out("data.txt"); // (1)
out << "Alice 90\nBob 85\n"; // (2)
out.close(); // (3)
ifstream in("data.txt"); // (4)
string name; int score;
vector<pair<string,int>> rec;
while (in >> name >> score) // (5)
rec.push_back({name, score});
for (auto &p : rec) // (6)
cout << p.first << ": " << p.second << "\n";
}
How it works
ofstreamopens a file for writing (creates it if missing).- Write two “name score” lines.
- Close the output stream (flush buffers).
ifstreamopens the same file for reading.- The extraction operator
>>reads values until EOF; each pair is pushed into the vector. - Iterate the vector and print each record.
Robustness tip: check
out/inwithif(!out)orif(!in)to catch open failures.
16. Templates & STL (algorithms + lambdas)
template<typename T>
T Max(T a, T b){ return (a>b) ? a : b; } // (1)
#include <vector>
#include <map>
#include <algorithm> // sort, find
#include <numeric> // accumulate
#include <iostream>
using namespace std;
int main(){
vector<int> v = {5,2,9,1};
sort(v.begin(), v.end()); // (2) 1 2 5 9
auto it = find(v.begin(), v.end(), 5); // (3)
if (it != v.end()) cout << "Found 5\n";
map<string,int> mp; // (4)
mp["Alice"]=90; mp["Bob"]=85;
int sum = accumulate(v.begin(), v.end(), 0, // (5)
[](int a,int b){ return a+b; }); // lambda
cout << "Sum=" << sum << "\n";
}
How it works
- A function template works for many types (as long as
>exists for them). sortreorders the vector (ascending by default).findsearches linearly; returns an iterator to the found element (orv.end()if not found).mapstores key→value pairs in sorted order by key.accumulatefolds values with a lambda that adds two numbers.
17. Organizing Code (headers + multiple files)
- Put class/struct declarations in
*.hpp(or*.h) and definitions in*.cpp. - Include headers where needed; compile all
.cppfiles together. - Keep functions small and focused; use meaningful names; document tricky parts.
Mini Project Student Score Manager (end-to-end)
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <numeric>
using namespace std;
struct Student { // (1)
string name;
int score;
};
class Database { // (2)
vector<Student> data; // holds all records
public:
void add(const string& n, int s){ data.push_back({n,s}); } // (3)
void load(const string& file){ // (4)
ifstream in(file);
string n; int s;
data.clear();
while (in >> n >> s) data.push_back({n,s});
}
void save(const string& file) const { // (5)
ofstream out(file);
for (auto &st: data) out << st.name << " " << st.score << "\n";
}
void report() const { // (6)
if (data.empty()){ cout<<"No data\n"; return; }
int best = max_element(data.begin(), data.end(),
[](const Student& a, const Student& b){
return a.score < b.score;
})->score;
double avg = accumulate(data.begin(), data.end(), 0.0,
[](double acc, const Student& s){ return acc + s.score; })
/ data.size();
cout << "Students: " << data.size() << "\n";
cout << "Average: " << avg << "\n";
cout << "Top scorers:\n";
for (auto &s: data)
if (s.score == best) cout << " - " << s.name << " (" << s.score << ")\n";
}
};
int main(){ // (7)
Database db;
db.add("Alice",90); db.add("Bob",85); db.add("Carol",90);
db.save("students.txt"); // write
Database db2;
db2.load("students.txt"); // read back
db2.report(); // print summary
}
How it works
Studentgroups related fields (name + score).Databaseencapsulates storage + operations (clean API, single responsibility).addappends a record to the in-memory vector.loadclears in-memory data, then reads pairs from a file into the vector.savewrites all records to a file (one per line).report- Finds the highest score using
max_elementwith a custom comparator. - Computes average using
accumulate. - Prints students who match the best score (handles ties).
- Finds the highest score using
maindemonstrates a real workflow: create → save → load → report.
Extensions to try: validate input ranges, handle empty/bad files, sort by score, or export CSV.
Practice Tasks (to lock in learning)
- Temperature converter (C↔F) with a
switchmenu and separate functions. - Factorial + Fibonacci using both loops and recursion.
- Read integers from a file into
vector<int>, then sort + min/max/median/average. BankAccountclass (deposit/withdraw, print statement to file, basic validations).- Word-frequency counter using
map<string,int>on a text file.
Common Errors & Debugging Tips
'g++' not recognized→ fix PATH or reopen terminal.- Missing
;or braces → pay attention to compiler line numbers. =vs==in conditions → use==for comparison.- Out-of-bounds indexes → stay within
[0, size). - Prefer smart pointers over raw
new/delete. - Add checks for file opens:
if (!in) { /* handle */ }
Summary
You’ve seen the end-to-end path: compile your first program, master variables, decisions, loops, functions, arrays/strings/vectors, pointers and memory, OOP and polymorphism, exceptions, files, templates, and core STL algorithms then put it together in a practical mini-project. If you publish this as a single article, add internal links to future problem sets, project galleries, and interview tips to maximize SEO and student engagement.
The approach followed at E Lectures reflects both academic depth and easy-to-understand explanations.
People also ask:
Yes if you go step-by-step with clear examples (like this article) and practice regularly.
Understand them conceptually, but use smart pointers (unique_ptr, shared_ptr) in modern code.
It offers optimized containers and algorithms, accelerating development and reducing bugs.
VS Code + C/C++ extension is light and popular. You can try full IDEs later.
Master loops, functions, arrays/vectors, maps/sets, sorting, binary search, and practice daily.

