Skip to content

C++ Quick Guide

C++ is a powerful, statically-typed, compiled, multi-paradigm programming language. It supports procedural, object-oriented, generic, and functional programming styles. Known for its performance, it’s widely used in systems programming, game development, high-frequency trading, embedded systems, and large-scale applications.

Considered a middle-level language, it offers low-level memory manipulation capabilities (like C) alongside high-level abstractions (like classes and templates). C++ evolves through standards (C++11, C++14, C++17, C++20, C++23…), with modern C++ emphasizing safety, expressiveness, and performance.

You need a C++ compiler to translate your source code (typically in .cpp files) into an executable program. Popular modern compilers include:

  • GCC (GNU Compiler Collection): Free, open-source, widely available on Linux, macOS (via Xcode Command Line Tools or package managers), and Windows (via MinGW or Cygwin).
  • Clang: Free, open-source compiler (part of the LLVM project), known for fast compilation and excellent diagnostics. Available on major platforms.
  • MSVC (Microsoft Visual C++): Part of Visual Studio on Windows. Offers a free Community edition.

Ensure your compiler supports a recent C++ standard (C++17 or later is recommended for modern features).

A minimal C++ program:

// Include necessary headers for standard library features
#include <iostream> // For input/output streams (like std::cout)
// main() is the entry point where program execution begins.
// It should return an integer status code (0 typically indicates success).
int main() {
// std::cout is the standard output stream (usually the console).
// << is the stream insertion operator.
// std::endl inserts a newline and flushes the output buffer.
std::cout << "Hello, Modern C++!" << std::endl;
return 0; // Indicate successful execution
}

Comments are ignored by the compiler and are used for explaining code.

// This is a single-line comment. It extends to the end of the line.
/*
This is a multi-line comment.
It can span several lines.
*/

C++ has several built-in (primitive) data types:

TypeKeywordTypical Use
BooleanboolTrue/false values (true, false)
CharactercharSingle characters (e.g., ‘a’, ’$’). Also used for small integers.
IntegerintWhole numbers (e.g., 10, -5, 0)
Floating pointfloatSingle-precision decimal numbers (e.g., 3.14f)
Double floating pointdoubleDouble-precision decimal numbers (e.g., 3.14159)
ValuelessvoidIndicates no type (used for function return types, pointers)
Wide characterwchar_tCharacters for larger character sets (implementation-defined)

Modifiers (signed, unsigned, short, long, long long) can alter the range and size of these types (see cpp_modifier_types.json).

A variable definition specifies its type and name, and allocates memory. Initialization gives it an initial value.

#include <string>
#include <vector>
int main() {
int score = 90; // C-style initialization
double temperature(25.5); // Constructor-style initialization
bool isActive{true}; // Uniform initialization (preferred in modern C++)
std::string playerName = "Alex"; // Initialization using string literal
std::vector<int> numbers{1, 2, 3}; // Uniform initialization for containers
// Type deduction with 'auto' (C++11)
auto count = 10; // count is deduced as int
auto message = "Processing..."; // message is deduced as const char*
auto pi = 3.14; // pi is deduced as double
return 0;
}

Always initialize your variables to avoid using indeterminate values.

Scope defines where a variable can be accessed:

  • Local Scope: Variables declared inside a function or block ({}) are only accessible within that function/block.
  • Global Scope: Variables declared outside any function have global scope and are accessible from anywhere in the file (after their declaration). Use global variables sparingly.
  • Class Scope: Members of a class are accessible within the class methods (and potentially outside, depending on access specifiers).
  • Namespace Scope: Variables declared within a namespace.

Literals are fixed values in code (e.g., 10, 3.14f, 'a', "Hello"). Constants are variables whose values cannot be changed after initialization.

const double PI = 3.14159; // 'const' keyword for runtime constants
constexpr int MAX_USERS = 100; // 'constexpr' for compile-time constants
// PI = 3.14; // Error: cannot assign to const variable
// MAX_USERS = 99; // Error: cannot assign to constexpr variable

Use const and constexpr to improve code safety and enable optimizations.

Storage class specifiers determine a variable’s lifetime and linkage:

  • auto (obsolete as storage class, keyword repurposed for type deduction in C++11)
  • register (hint to compiler, largely ignored by modern optimizers)
  • static: Inside a function/block, extends lifetime to the entire program duration. At global/namespace scope, limits linkage to the current translation unit.
  • extern: Declares a variable defined elsewhere (often in another file), enabling linkage.
  • thread_local (C++11): Specifies that a variable has thread-specific storage duration.
  • mutable: Allows a class member declared mutable to be modified even within a const member function or through a const object.

C++ offers a rich set of operators:

  • Arithmetic: +, -, *, /, % (modulo), ++ (increment), -- (decrement)
  • Relational: == (equal), != (not equal), >, <, >=, <=
  • Logical: && (AND), || (OR), ! (NOT)
  • Bitwise: & (AND), | (OR), ^ (XOR), ~ (NOT), << (left shift), >> (right shift)
  • Assignment: =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
  • Member Access: . (object member), -> (pointer member)
  • Other: sizeof, & (address-of), * (dereference), ?: (ternary conditional), , (comma), () (function call), [] (array subscript), typeid, casting operators (static_cast, dynamic_cast, const_cast, reinterpret_cast), new, delete, :: (scope resolution)

Loops execute code repeatedly:

Loop TypeDescription
while loopRepeats while a condition is true (checked before each iteration).
for loopExecutes for a controlled number of times (initialization, condition, update).
do...while loopRepeats while a condition is true (checked after each iteration; body always executes at least once).
Range-based for (C++11)Iterates over all elements in a range (e.g., container, array). Preferred for simple iteration.
#include <vector>
#include <iostream>
int main() {
std::vector<int> nums = {10, 20, 30};
// Range-based for loop (modern C++)
for (int num : nums) {
std::cout << num << " "; // Output: 10 20 30
}
std::cout << std::endl;
// Traditional for loop
for (size_t i = 0; i < nums.size(); ++i) {
std::cout << nums[i] << " "; // Output: 10 20 30
}
std::cout << std::endl;
return 0;
}

Statements that control execution based on conditions:

StatementDescription
if statementExecutes code if a condition is true.
if...else statementExecutes one block if true, another if false.
if...else if...elseChain multiple conditions.
switch statementTests a variable against a list of constant values (case).
Ternary Operator (?:)Shorthand for simple if-else expressions.

Functions group code to perform a specific task.

// Function definition
return_type function_name(parameter_list) {
// function body
return value; // Optional, depends on return_type
}
  • return_type: Data type of the value the function returns (void if none).
  • function_name: Identifier for the function.
  • parameter_list: Comma-separated list of input parameters (type and name).
  • function body: Code executed when the function is called.

Functions promote code reuse and modularity.

Use primitive types (int, float, double) for numbers. Include <cmath> for math functions.

#include <cmath> // For math functions
#include <iostream>
int main() {
double angle_degrees = 45.0;
double angle_radians = angle_degrees * M_PI / 180.0; // M_PI often requires _USE_MATH_DEFINES or similar
std::cout << "Square root of 16: " << std::sqrt(16.0) << std::endl; // Output: 4
std::cout << "2 raised to power 10: " << std::pow(2.0, 10.0) << std::endl; // Output: 1024
std::cout << "Cosine of 45 degrees: " << std::cos(angle_radians) << std::endl; // Output: ~0.7071
return 0;
}

For high-quality random numbers, use the <random> header (see cpp_numbers.json).

Arrays store fixed-size sequences of elements. Prefer std::vector or std::array over raw C-style arrays in modern C++.

#include <vector> // For std::vector (dynamic size)
#include <array> // For std::array (fixed size, stack-allocated)
#include <iostream>
#include <numeric> // For std::iota
int main() {
// C-style array (use sparingly)
int c_array[5];
c_array[0] = 10;
// std::array (fixed size, bounds checking with .at())
std::array<int, 5> modern_array;
std::iota(modern_array.begin(), modern_array.end(), 100); // Fill with 100, 101, ...
std::cout << "std::array element: " << modern_array.at(1) << std::endl; // Output: 101
// std::vector (dynamic size, manages its own memory)
std::vector<int> dynamic_vector;
dynamic_vector.push_back(10);
dynamic_vector.push_back(20);
dynamic_vector.push_back(30);
std::cout << "Vector size: " << dynamic_vector.size() << std::endl; // Output: 3
std::cout << "Vector element: " << dynamic_vector[1] << std::endl; // Output: 20
// Iterate using range-based for
for (int val : dynamic_vector) {
std::cout << val << " "; // Output: 10 20 30
}
std::cout << std::endl;
return 0;
}

Use the std::string class from the <string> header for text manipulation. Avoid C-style character arrays (char[]) for general string handling.

#include <string>
#include <iostream>
int main() {
std::string greeting = "Hello";
std::string name = "World";
std::string message;
// Concatenation
message = greeting + ", " + name + "!";
std::cout << message << std::endl; // Output: Hello, World!
// Length/Size
std::cout << "Message length: " << message.length() << std::endl;
// Substring
std::cout << "Substring: " << message.substr(0, 5) << std::endl; // Output: Hello
return 0;
}

Classes are blueprints for objects, encapsulating data (members) and behavior (methods).

#include <iostream>
#include <string>
class Box {
private: // Data members are usually private (Encapsulation)
double length = 1.0;
double breadth = 1.0;
double height = 1.0;
public: // Methods (and constructors) are often public
// Constructor (initializes the object)
Box(double l, double b, double h) : length(l), breadth(b), height(h) {
std::cout << "Box created with dimensions: " << l << ", " << b << ", " << h << std::endl;
}
// Member function (method)
double getVolume() const { // const indicates the method doesn't modify the object
return length * breadth * height;
}
// Destructor (cleans up when object is destroyed)
~Box() {
std::cout << "Box destroyed." << std::endl;
}
};
int main() {
// Create an object (instance) of the Box class
Box myBox(5.0, 6.0, 7.0);
// Access public members using the dot (.) operator
std::cout << "Volume of myBox: " << myBox.getVolume() << std::endl;
return 0; // myBox goes out of scope here, destructor ~Box() is called
}

Key OOP concepts like Encapsulation, Abstraction, Inheritance, and Polymorphism are central to C++ (see cpp_object_oriented.json).

Allows creating new classes (derived) based on existing ones (base), promoting code reuse and “is-a” relationships.

class Shape { // Base class
public:
virtual double getArea() const = 0; // Pure virtual function (makes Shape abstract)
virtual ~Shape() = default; // Virtual destructor!
};
class Rectangle : public Shape { // Derived class
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
double getArea() const override { // Implement base virtual function, use 'override'
return width * height;
}
};

See cpp_inheritance.json for details on access specifiers, virtual functions, override, final, and multiple inheritance.

Allows objects of different derived classes to be treated through a common base class interface, typically using pointers or references.

#include <iostream>
#include <memory> // For std::unique_ptr
#include <vector>
// Using Shape and Rectangle from Inheritance example...
void printArea(const Shape& shape) { // Takes base class reference
std::cout << "Area: " << shape.getArea() << std::endl;
}
int main() {
Rectangle rect(10, 5);
// Circle circ(7); // Assuming a Circle class derived from Shape
printArea(rect); // Calls Rectangle::getArea()
// printArea(circ); // Would call Circle::getArea()
// Using base class pointers (smart pointers preferred)
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Rectangle>(4, 3));
// shapes.push_back(std::make_unique<Circle>(2));
for (const auto& shapePtr : shapes) {
printArea(*shapePtr); // Calls appropriate getArea() via virtual dispatch
}
return 0;
}

Requires virtual functions in the base class. Always include a virtual destructor in base classes intended for polymorphic use.

Allows multiple functions or operators with the same name but different parameters (compile-time polymorphism).

void display(int i) { std::cout << "Int: " << i << std::endl; }
void display(double d) { std::cout << "Double: " << d << std::endl; }
void display(const std::string& s) { std::cout << "String: " << s << std::endl; }
display(10); // Calls int version
display(3.14); // Calls double version
display("Test"); // Calls string version

Use <fstream> for file I/O (std::ifstream for input, std::ofstream for output).

#include <fstream> // For file streams
#include <iostream> // For console I/O
#include <string> // For std::string
#include <vector>
int main() {
std::string filename = "mydata.txt";
// Write to a file (using RAII with ofstream)
{
std::ofstream outfile(filename); // Opens file in constructor
if (!outfile) { // Always check if file opened successfully
std::cerr << "Error opening " << filename << " for writing." << std::endl;
return 1;
}
outfile << "Line 1: Hello from C++\n";
outfile << "Line 2: Files are useful.\n";
} // outfile goes out of scope, file is automatically closed
// Read from a file
{
std::ifstream infile(filename);
if (!infile) {
std::cerr << "Error opening " << filename << " for reading." << std::endl;
return 1;
}
std::string line;
std::cout << "\nReading from file:" << std::endl;
while (std::getline(infile, line)) { // Read line by line
std::cout << line << std::endl;
}
} // infile goes out of scope, file is automatically closed
return 0;
}

Always check if file streams were opened successfully. RAII (using stream objects directly) ensures files are closed even if errors occur.

This quick guide provides a starting point. C++ is a deep language; explore resources like cppreference.com and dedicated tutorials for more.