Advertisement

Learn C++ Intermediate: Advanced Concepts and Techniques

You've got C++ basics down. Now let's dive into intermediate concepts - pointers, memory management, classes, and more. These are what make C++ powerful (and sometimes tricky).

This course assumes you know C++ basics. If you don't, check out our C++ for Beginners course first.

Lesson 1: Pointers

Pointers store memory addresses. They're one of C++'s most powerful (and confusing) features:

int x = 10;
int* ptr = &x;  // ptr stores the address of x

cout << x << endl;      // 10 (value)
cout << &x << endl;     // address of x
cout << ptr << endl;    // address of x
cout << *ptr << endl;   // 10 (dereference - get value at address)

*ptr = 20;  // Change value through pointer
cout << x << endl;  // 20

& gets the address. * dereferences (gets the value at an address). Pointers let you work with memory directly.

Lesson 2: Dynamic Memory

Allocate memory dynamically with new and free it with delete:

// Allocate memory
int* ptr = new int(10);

// Use it
cout << *ptr << endl;  // 10

// Free memory (IMPORTANT - prevents memory leaks)
delete ptr;
ptr = nullptr;  // Good practice

Important: Always delete what you new. Forgetting to delete causes memory leaks. In modern C++, prefer smart pointers (we'll cover those later).

Lesson 3: Classes

Classes let you create your own data types:

class Rectangle {
private:
    double width;
    double height;

public:
    Rectangle(double w, double h) {
        width = w;
        height = h;
    }
    
    double area() {
        return width * height;
    }
    
    void setWidth(double w) {
        width = w;
    }
};

Rectangle rect(5.0, 3.0);
cout << rect.area() << endl;  // 15

Classes encapsulate data and functions. private members can't be accessed outside the class. public members can be accessed.

Lesson 4: Vectors

Vectors are dynamic arrays. They're better than regular arrays for most uses:

#include <vector>

vector<int> numbers;

// Add elements
numbers.push_back(10);
numbers.push_back(20);
numbers.push_back(30);

// Access elements
cout << numbers[0] << endl;  // 10

// Size
cout << numbers.size() << endl;  // 3

// Loop through
for (int num : numbers) {
    cout << num << " ";
}

Vectors grow automatically. They're part of the Standard Template Library (STL) and much more convenient than arrays.

Advertisement

Lesson 5: Inheritance

Inheritance lets you create new classes based on existing ones:

class Animal {
protected:
    string name;
public:
    Animal(string n) : name(n) {}
    virtual void speak() = 0;  // Pure virtual function
};

class Dog : public Animal {
public:
    Dog(string n) : Animal(n) {}
    void speak() override {
        cout << name << " says woof!" << endl;
    }
};

Dog dog("Buddy");
dog.speak();  // Buddy says woof!

Inheritance reduces code duplication. Child classes inherit from parent classes. virtual and override enable polymorphism.

Lesson 6: File I/O

Read and write files:

#include <fstream>

// Write to file
ofstream outFile("output.txt");
outFile << "Hello, World!" << endl;
outFile.close();

// Read from file
ifstream inFile("output.txt");
string line;
while (getline(inFile, line)) {
    cout << line << endl;
}
inFile.close();

ofstream for output, ifstream for input. Always close files when done.

Lesson 7: Exception Handling

Handle errors gracefully:

try {
    int x = 10;
    int y = 0;
    if (y == 0) {
        throw runtime_error("Division by zero!");
    }
    int result = x / y;
} catch (const exception& e) {
    cout << "Error: " << e.what() << endl;
}

throw raises exceptions. catch handles them. Makes programs more robust.

Lesson 8: Smart Pointers

Smart pointers automatically manage memory. Use them instead of raw pointers when possible:

#include <memory>

// unique_ptr - automatically deletes when out of scope
unique_ptr<int> ptr = make_unique<int>(10);
cout << *ptr << endl;  // 10
// No need to delete - automatically freed

// shared_ptr - multiple owners
shared_ptr<int> shared = make_shared<int>(20);
shared_ptr<int> shared2 = shared;  // Both point to same memory

Smart pointers prevent memory leaks. Use unique_ptr for single ownership, shared_ptr for shared ownership.

Best Practices

  • Use smart pointers: Prefer smart pointers over raw pointers
  • Use vectors: Prefer vectors over arrays when possible
  • Initialize variables: Always initialize variables
  • Handle errors: Use exceptions for error handling
  • Follow RAII: Resource Acquisition Is Initialization - acquire resources in constructors, release in destructors

Pro Tip: Modern C++ (C++11 and later) has many improvements. Use smart pointers, auto keyword, range-based for loops, and other modern features. They make code safer and easier to write.

Common Questions

When should I use pointers?

Use pointers when you need dynamic memory, when passing large objects (to avoid copying), or when you need multiple references to the same object. In modern C++, prefer smart pointers over raw pointers.

What's the difference between arrays and vectors?

Arrays are fixed size, vectors are dynamic. Arrays are faster but less flexible. For most uses, vectors are better. Use arrays only when you need the performance or when size is known at compile time.

How do I avoid memory leaks?

Use smart pointers. They automatically manage memory. If you must use raw pointers, always match new with delete, and set pointers to nullptr after deleting.

Keep Learning C++

You've learned intermediate C++ concepts. Practice with projects that use pointers, classes, and memory management. Build programs that read files, use classes, and manage memory. The more you practice, the more comfortable you'll get with these concepts.

Advertisement