Lesson 1 of 25

Introduction to C++

What is C++?

C++ is a general-purpose programming language built for the situations where speed and control over the machine genuinely matter. Bjarne Stroustrup began it in 1979 at Bell Labs under the name "C with Classes", and it was renamed C++ in 1983. The name is a joke that is also a description: ++ is C's increment operator, so C++ reads as "one better than C".

To understand why the language exists, you need to know what it was reacting against. C was fast and sat very close to the hardware, but it gave you almost nothing for organising a large program — no classes, no way to write one sorting routine that works for every type, no automatic cleanup when a function ends. The languages that did offer those conveniences at the time paid for them with a heavy runtime system. Stroustrup wanted the abstractions without the bill.

That ambition became the language's design rule, usually stated as the zero-overhead principle: you should not pay for a feature you do not use, and a feature you do use should be as fast as the equivalent code you would have written by hand. It explains most of C++'s personality. C++ will not check that your array index is in range, it will not collect your garbage, and it will not stop you reading a variable you never gave a value to — because each of those checks costs time, and somewhere there is a program that cannot spare it.

The practical consequence for you is that C++ hands you both the power and the responsibility. A C++ program can be dramatically faster than the same logic in Python, and it can also crash in ways that Python simply cannot. Most of this course is about earning the first without inviting the second.

  • Game engines — Unreal Engine, and the bulk of console and PC game code
  • Browsers — the rendering engine and JavaScript engine inside Chrome and Firefox
  • Databases — MySQL, and the storage engines underneath several NoSQL systems
  • Embedded and real-time systems — vehicle software, medical devices, robotics controllers
  • Finance and scientific computing, where a few microseconds are the whole product
  • Competitive programming and placement interviews, because the standard library is both fast and complete

Your First Program, Line by Line

Below is the smallest complete C++ program worth writing. It is four meaningful lines, and every one of them is doing something you should be able to explain.

#include <iostream> is a preprocessor directive. Before the compiler proper sees your file, a stage called the preprocessor runs and pastes the entire contents of the iostream header into your file at that point. That header declares std::cout and std::cin. If you leave the include out, the compiler has never heard of cout and says so.

int main() is the entry point. Every C++ program has exactly one main, and execution starts at its first statement. The int is the value the program hands back to the operating system when it finishes; by convention 0 means success and anything else means failure. This is what a shell script is reading when it checks whether your program worked.

std::cout << "Hello, World!\n"; sends text to standard output. cout is an object, not a function, and << is an operator that has been given a second meaning for streams — it is the same symbol as the bitwise left-shift, reused. Because each << returns the stream again, you can chain them: cout << a << b << c works left to right.

The std:: in front of cout is a namespace qualifier. Everything in the standard library lives inside a namespace called std, so that the library's names cannot collide with yours. Finally, return 0; ends the program successfully. main is the one function in C++ that is allowed to omit its return statement — fall off the end and the compiler inserts return 0; for you — but writing it out is clearer.

Example
#include <iostream>

int main() {
    std::cout << "Hello, World!\n";
    return 0;
}

// Compile:  g++ -std=c++17 -Wall -o hello hello.cpp
// Run:      ./hello        (Windows: hello.exe)

Compiled, Not Interpreted

If you came from Python or JavaScript, this is the biggest change in your working habits. Those languages read your source file and execute it directly. C++ does not run your source at all. A separate program, the compiler, translates your source into machine code for one specific kind of processor and operating system, and only then can you run the result.

That translation happens in three stages. The preprocessor handles the lines starting with # and produces one large text file. The compiler turns that text into an object file of machine code, checking types and syntax on the way. The linker joins your object files together with the standard library and produces the final executable. Knowing these three stages saves you real time, because their error messages look completely different and tell you different things.

A compiler error means your code is not valid C++ — a missing semicolon, a misspelled name, a type mismatch. A linker error means your code was valid but the machine code for something you called was never found; the classic case is declaring a function and never writing its body. The message undefined reference to ... is a linker error, and no amount of staring at the line it mentions will help, because the problem is somewhere else entirely.

The upside of all this ceremony is that a large class of mistakes is caught before your program ever runs. In Python, passing a string where a number was expected surfaces at the moment that line executes, possibly in production at 2 a.m. In C++, it usually will not compile.

Example
# the three stages, made visible
g++ -E main.cpp -o main.i     # 1. preprocess only
g++ -c main.cpp -o main.o     # 2. compile to an object file
g++ main.o -o app             # 3. link into an executable

# normally you run all three at once
g++ -std=c++17 -Wall -Wextra -o app main.cpp

# A COMPILER error — the code is not valid C++:
#   error: 'cout' was not declared in this scope
#   (you forgot #include <iostream>)

# A LINKER error — valid C++, but no body was ever written:
#   undefined reference to 'helper()'
Notes
  • Always compile with -Wall -Wextra. These turn on warnings for code that is legal but almost certainly wrong, and in C++ a warning you ignored is very often the bug you spend the next evening hunting.

About using namespace std;

Almost every tutorial you will find opens with using namespace std;, and it is worth understanding exactly what that line buys you and what it costs, because opinions on it are strong and often unexplained.

The line tells the compiler that when it sees an unqualified name like cout, it may also look inside the std namespace. That is the whole effect. It lets you type cout instead of std::cout, string instead of std::string, and so on.

The cost is that you have just dumped several thousand standard-library names into your file's scope, and if any of them collide with yours, the results range from a confusing error to a program that quietly calls the wrong function. The genuinely nasty case is a header file: if you write using namespace std; inside a .h file, every single file that includes it inherits the problem, and that person is not you.

The rule most working C++ programmers settle on: never put it in a header, it is tolerable in a short .cpp file or a competitive-programming submission, and in anything you intend to maintain, prefer writing std:: or importing only the few names you need. This course writes std:: explicitly, partly for correctness and partly because seeing it makes it obvious which parts of the code came from the standard library.

Example
#include <iostream>
#include <string>

// Option A — fully qualified (used throughout this course)
int main() {
    std::string name = "Ananya";
    std::cout << "Hi " << name << '\n';
}

// Option B — pull in just the names you need
// using std::cout;
// using std::string;

// Option C — the whole namespace. Fine in a small .cpp file,
// never acceptable in a header that others will include.
// using namespace std;
Notes
  • A real collision people hit: the standard library has std::count, and beginners very often name a variable count. With using namespace std; in scope, the resulting error message mentions template argument deduction and is almost impossible to read for a first-year student.

What C++ Trusts You With

There is one concept you should meet on day one, because it explains behaviour that will otherwise seem like magic or like a broken compiler: undefined behaviour. The C++ standard describes what your program must do for correct code. For certain mistakes it deliberately says nothing at all — the behaviour is undefined, and the compiler is allowed to do literally anything, including producing a program that appears to work.

That last part is what catches students out. Reading past the end of an array might print a garbage number today, crash tomorrow, and pass every test on your machine while failing on the evaluator's. The mistake is not "sometimes" wrong; it is always wrong, and the symptom is merely unreliable. When a C++ program behaves differently on two machines, or changes behaviour when you add an unrelated cout, undefined behaviour is the first thing to suspect.

None of this should make you nervous about learning the language. It should make you precise. The rest of this course introduces the tools C++ gives you to avoid these traps almost entirely: std::vector and std::string instead of raw memory, references instead of pointers where possible, smart pointers instead of manual delete, and the habit of initialising every variable at the moment you declare it.

  • Reading a variable you never initialised — the value is whatever bytes were already there
  • Indexing past the end of an array or a std::vector with []
  • Using a pointer after the memory it pointed to has been freed
  • Signed integer overflow — not a wraparound you can rely on, but undefined
  • Dereferencing a null pointer
  • Forgetting to return a value from a non-void function
Notes
  • While you are learning, build with g++ -std=c++17 -Wall -Wextra -fsanitize=address,undefined -g. The sanitizers add run-time checks that turn many of these silent mistakes into a clear message naming the file and line. Turn them off only for final performance builds.
Ask AI