C++ is a compiled language used for command-line tools, games, databases, embedded software and other programs that need control over resources. A compiler checks source code and translates it into machine code. The standard library supplies reusable facilities such as strings, collections, files and threads.
This course uses C++20, a specific language standard. Always select it explicitly: a compiler's default can differ between installations. You need both a compiler and a compatible standard library. GCC and Clang are suitable toolchains; their support tables help diagnose a missing feature. The examples avoid vendor extensions and external libraries.
Build your first program
Save this complete program as hello.cpp:
#include <iostream>
#include <string>
int main() {
const std::string language{"C++20"};
std::cout << "Learning " << language << '\n';
return 0;
}
In a terminal in the same directory, compile and run it:
clang++ -std=c++20 -Wall -Wextra -Wpedantic -g hello.cpp -o hello
./hello
These commands use a POSIX-style shell. On Windows, use the corresponding compiler environment and executable path. You can replace clang++ with g++ when GCC is installed. The program prints Learning C++20 followed by a newline and returns a successful exit status.
#include makes library declarations available. std:: identifies names in the standard-library namespace. main is the program's entry function; returning zero signals success. Braces delimit its body, and semicolons finish declarations and expression statements. std::cout writes to standard output; << sends each value into the stream.
The options select the language, enable useful warnings, include debugging information and choose the output filename. -Wall does not enable every possible warning. Read warnings before adding more code: they often expose mistaken assumptions before a test does.
Understand the build pipeline
Preprocessing handles directives such as #include. Compilation checks a translation unit, meaning one source file after preprocessing, and produces object code. Linking combines object files and libraries, resolving references between them. A single compiler-driver command can run all these steps.
This distinction helps interpret failures. A missing semicolon is a compilation error. Calling a declared function without providing its definition often produces an undefined-reference or undefined-symbol linker error. Running an executable that calculates the wrong answer is a logic error, even if its build was clean.
For a multi-file exercise, save these three files in a new directory. The header uses an include guard, which prevents repeated declarations within one translation unit.
greeting.hpp:
#ifndef GREETING_HPP
#define GREETING_HPP
#include <string>
std::string greeting();
#endif
greeting.cpp:
#include "greeting.hpp"
std::string greeting() {
return "Hello from two source files";
}
main.cpp:
#include "greeting.hpp"
#include <iostream>
int main() {
std::cout << greeting() << '\n';
}
clang++ -std=c++20 -Wall -Wextra -Wpedantic -g main.cpp greeting.cpp -o greeting
./greeting
The output is Hello from two source files. Leaving greeting.cpp out of that command demonstrates a linker failure. Headers normally expose interfaces; source files provide ordinary function definitions. Defining the same ordinary function in multiple translation units violates the one-definition rule. Templates and inline functions have additional rules introduced later.
Build habits and pitfalls
Use -g while learning so a debugger can connect execution to source lines. An optimized build can use -O2; optimization does not repair incorrect code. Undefined behavior means the language imposes no requirements after certain invalid operations, such as an out-of-bounds vector access. Successful compilation alone cannot establish correctness.
Include the header for every library facility you use. Avoid nonstandard convenience headers such as bits/stdc++.h, variable-length built-in arrays and assumptions about one operating system. Keep generated executables outside your source tree when working in a shared repository. As the project grows, a build system can track dependencies; understanding this direct command remains useful when diagnosing it.
Practice and solution guidance
- Change the first program to print your name and a second line describing your goal. Guidance: use another stream insertion and newline; preserve a successful exit status.
- Build the three-file example, then omit
greeting.cpp. Guidance: identify the unresolved symbol and explain why a declaration was enough to compile the caller but insufficient to link it. - Add a second function to the header and implementation. Guidance: declare it once, define it once, call it from
main, then rebuild both source files.
Primary references
- ISO's C++20 publication record identifies the standard used here.
- GCC language-standard options and warning options explain the build flags.
- GCC C++ support documents compiler feature support.

