How to Learn C Plus Plus: A Comprehensive Guide

Learning How To Learn C Plus Plus effectively can open doors to incredible opportunities in software development. At LEARNS.EDU.VN, we provide a structured, engaging, and comprehensive path for mastering C++, whether you are a beginner or an experienced programmer seeking to deepen your skills. Explore LEARNS.EDU.VN for more insights on C++ development, programming tutorials, and coding resources.

1. Understanding the Basics of C++ Programming

Before diving into the complexities, grasping the fundamental concepts of C++ is crucial. This section outlines the core principles that underpin C++ programming, providing a solid foundation for further learning.

1.1. Introduction to C++

C++ is a versatile, high-performance programming language used in a wide array of applications, from operating systems and game development to financial modeling and embedded systems. Developed by Bjarne Stroustrup in the late 1970s, C++ extends the C language with object-oriented features, offering both low-level memory manipulation and high-level abstractions. Its efficiency and control make it a favorite for performance-critical applications, while its rich feature set supports complex software architectures.

1.2. Key Features of C++

C++ boasts several key features that make it a powerful choice for developers:

  • Object-Oriented Programming (OOP): Supports encapsulation, inheritance, and polymorphism, enabling modular and reusable code.
  • High Performance: Allows direct memory access and efficient resource management, leading to optimized performance.
  • Standard Template Library (STL): Provides a rich set of data structures and algorithms, promoting code reuse and efficiency.
  • Cross-Platform Compatibility: Can be compiled and run on various operating systems, making it suitable for diverse development environments.
  • Large Community and Ecosystem: Benefits from extensive online resources, libraries, and frameworks, fostering collaboration and innovation.

1.3. Setting Up Your Development Environment

To start learning C++, setting up a suitable development environment is essential. This typically involves installing a compiler, an Integrated Development Environment (IDE), and configuring the necessary tools.

1.3.1. Installing a C++ Compiler

A compiler translates C++ code into machine-executable code. Popular C++ compilers include:

  • GCC (GNU Compiler Collection): A free and open-source compiler available for various platforms.
  • Clang: Another open-source compiler known for its speed and diagnostics.
  • Microsoft Visual C++ (MSVC): A compiler provided with Microsoft Visual Studio, ideal for Windows development.

Installation steps vary depending on your operating system. For instance, on Windows, you can install MSVC through the Visual Studio Installer, while on Linux, GCC or Clang can be installed via the package manager.

1.3.2. Choosing an Integrated Development Environment (IDE)

An IDE provides a comprehensive environment for writing, compiling, and debugging code. Popular C++ IDEs include:

  • Visual Studio: A feature-rich IDE with excellent debugging tools and integration with Microsoft technologies.
  • Code::Blocks: A free, open-source, and cross-platform IDE that is lightweight and customizable.
  • Eclipse: A versatile IDE with extensive plugin support, suitable for large projects.
  • CLion: A cross-platform IDE by JetBrains, offering smart code completion and analysis features.

1.3.3. Configuring Your IDE

After installing your IDE, configure it to use the installed C++ compiler. This usually involves specifying the compiler path in the IDE settings. Additionally, set up build configurations (Debug and Release) to optimize your code for different purposes. Debug builds include debugging information, while Release builds are optimized for performance.

1.4. Writing Your First C++ Program

Let’s create a simple “Hello, World” program to ensure your development environment is correctly set up:

#include <iostream>

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

This program includes the <iostream> header for input/output operations, defines the main function (the entry point of the program), and uses std::cout to print “Hello, World!” to the console. Save this code in a file named hello.cpp and compile it using your IDE or compiler. Run the executable to see the output.

1.5. Understanding the Structure of a C++ Program

A C++ program typically consists of the following elements:

  • Header Files: Include declarations of functions and classes (e.g., <iostream>, <vector>).
  • Main Function: The entry point of the program where execution begins.
  • Statements: Instructions that perform actions (e.g., variable declarations, assignments, function calls).
  • Functions: Blocks of code that perform specific tasks.
  • Classes: Blueprints for creating objects, defining data and behavior.
  • Comments: Explanations in the code ignored by the compiler, used for documentation.

1.6. Basic Syntax and Semantics

Understanding the basic syntax and semantics is essential for writing correct C++ code:

  • Variables: Used to store data (e.g., int x = 10;, double pi = 3.14;).
  • Data Types: Specify the type of data a variable can hold (e.g., int, double, char, bool).
  • Operators: Perform operations on variables (e.g., +, -, *, /, =, ==).
  • Control Structures: Control the flow of execution (e.g., if, else, for, while).
  • Functions: Defined using a return type, name, and parameters (e.g., int add(int a, int b) { return a + b; }).

1.7. Common Mistakes to Avoid

Beginners often make common mistakes that can lead to errors. Here are some to watch out for:

  • Uninitialized Variables: Always initialize variables before using them to avoid undefined behavior.
  • Missing Semicolons: C++ statements must end with a semicolon.
  • Incorrect Data Types: Using the wrong data type for a variable can lead to unexpected results.
  • Memory Leaks: Ensure dynamically allocated memory is properly deallocated using delete.
  • Off-by-One Errors: When using loops and arrays, ensure you are not accessing elements outside the valid range.

By understanding these basics, you will be well-prepared to tackle more advanced topics in C++. For further in-depth learning, explore the resources at LEARNS.EDU.VN, where you can find detailed tutorials, practice exercises, and expert guidance.

2. Mastering Fundamental C++ Concepts

With a basic understanding of C++, the next step is to master the fundamental concepts that form the building blocks of the language. This section covers essential topics such as variables, data types, control structures, and functions.

2.1. Variables and Data Types

Variables are used to store data, and data types specify the kind of data a variable can hold. Understanding variables and data types is crucial for writing effective C++ programs.

2.1.1. Declaring and Initializing Variables

In C++, you must declare a variable before using it. The declaration specifies the variable’s name and data type:

int age;        // Declares an integer variable named 'age'
double salary;  // Declares a double variable named 'salary'
char grade;     // Declares a character variable named 'grade'

You can also initialize a variable at the time of declaration:

int age = 30;           // Declares and initializes 'age' to 30
double salary = 50000.0;  // Declares and initializes 'salary' to 50000.0
char grade = 'A';        // Declares and initializes 'grade' to 'A'

2.1.2. Common Data Types

C++ provides several built-in data types:

  • int: Integer numbers (e.g., -10, 0, 42).
  • double: Floating-point numbers with double precision (e.g., 3.14, -2.71, 6.02e23).
  • float: Floating-point numbers with single precision (e.g., 3.14f, -2.71f).
  • char: Single characters (e.g., 'A', 'z', '9').
  • bool: Boolean values (true or false).
  • std::string: Sequence of characters (e.g., "Hello, World!").

2.1.3. Type Inference with auto

C++11 introduced the auto keyword, which allows the compiler to deduce the data type of a variable from its initializer:

auto age = 30;           // 'age' is deduced as int
auto salary = 50000.0;  // 'salary' is deduced as double
auto grade = 'A';        // 'grade' is deduced as char
auto message = "Hello";   // 'message' is deduced as const char*

Using auto can make your code more readable and maintainable, especially when dealing with complex types.

2.2. Operators and Expressions

Operators perform operations on variables and values. Understanding different types of operators and how they are used in expressions is crucial for writing effective C++ code.

2.2.1. Arithmetic Operators

Arithmetic operators perform mathematical operations:

  • +: Addition
  • -: Subtraction
  • *: Multiplication
  • /: Division
  • %: Modulus (remainder)
int a = 10;
int b = 3;
int sum = a + b;      // sum = 13
int difference = a - b; // difference = 7
int product = a * b;    // product = 30
int quotient = a / b;   // quotient = 3
int remainder = a % b;  // remainder = 1

2.2.2. Assignment Operators

Assignment operators assign values to variables:

  • =: Simple assignment
  • +=: Add and assign
  • -=: Subtract and assign
  • *=: Multiply and assign
  • /=: Divide and assign
  • %=: Modulus and assign
int x = 5;
x += 3;  // x = 8 (x = x + 3)
x -= 2;  // x = 6 (x = x - 2)
x *= 4;  // x = 24 (x = x * 4)
x /= 3;  // x = 8 (x = x / 3)
x %= 5;  // x = 3 (x = x % 5)

2.2.3. Comparison Operators

Comparison operators compare values:

  • ==: Equal to
  • !=: Not equal to
  • >: Greater than
  • <: Less than
  • >=: Greater than or equal to
  • <=: Less than or equal to
int a = 10;
int b = 5;
bool isEqual = (a == b);        // isEqual = false
bool isNotEqual = (a != b);     // isNotEqual = true
bool isGreaterThan = (a > b);    // isGreaterThan = true
bool isLessThan = (a < b);       // isLessThan = false
bool isGreaterOrEqual = (a >= b); // isGreaterOrEqual = true
bool isLessOrEqual = (a <= b);    // isLessOrEqual = false

2.2.4. Logical Operators

Logical operators perform logical operations:

  • &&: Logical AND
  • ||: Logical OR
  • !: Logical NOT
bool condition1 = true;
bool condition2 = false;
bool andResult = (condition1 && condition2); // andResult = false
bool orResult = (condition1 || condition2);  // orResult = true
bool notResult = !condition1;               // notResult = false

2.3. Control Structures

Control structures allow you to control the flow of execution in your program. They include conditional statements and loops.

2.3.1. Conditional Statements: if, else if, else

The if statement executes a block of code if a condition is true:

int age = 20;
if (age >= 18) {
    std::cout << "You are an adult." << std::endl;
}

The else statement executes a block of code if the condition in the if statement is false:

int age = 16;
if (age >= 18) {
    std::cout << "You are an adult." << std::endl;
} else {
    std::cout << "You are not an adult." << std::endl;
}

The else if statement allows you to check multiple conditions:

int score = 85;
if (score >= 90) {
    std::cout << "A" << std::endl;
} else if (score >= 80) {
    std::cout << "B" << std::endl;
} else if (score >= 70) {
    std::cout << "C" << std::endl;
} else {
    std::cout << "D" << std::endl;
}

2.3.2. Loops: for, while, do-while

The for loop executes a block of code a specified number of times:

for (int i = 0; i < 10; ++i) {
    std::cout << "Iteration: " << i << std::endl;
}

The while loop executes a block of code as long as a condition is true:

int count = 0;
while (count < 5) {
    std::cout << "Count: " << count << std::endl;
    ++count;
}

The do-while loop executes a block of code at least once, and then continues to execute as long as a condition is true:

int num = 0;
do {
    std::cout << "Number: " << num << std::endl;
    ++num;
} while (num < 3);

2.3.3. switch Statement

The switch statement allows you to select one of several code blocks to execute based on the value of a variable:

int day = 3;
switch (day) {
    case 1:
        std::cout << "Monday" << std::endl;
        break;
    case 2:
        std::cout << "Tuesday" << std::endl;
        break;
    case 3:
        std::cout << "Wednesday" << std::endl;
        break;
    default:
        std::cout << "Other day" << std::endl;
}

2.4. Functions

Functions are reusable blocks of code that perform specific tasks. They are essential for organizing and structuring your C++ programs.

2.4.1. Defining and Calling Functions

To define a function, you need to specify its return type, name, and parameters:

int add(int a, int b) {
    return a + b;
}

To call a function, use its name followed by parentheses, passing any required arguments:

int result = add(5, 3);  // result = 8
std::cout << "Result: " << result << std::endl;

2.4.2. Function Parameters and Return Values

Functions can take parameters as input and return a value as output. Parameters are specified in the function definition, and the return value is specified by the return type:

double calculateArea(double radius) {
    double area = 3.14159 * radius * radius;
    return area;
}

double area = calculateArea(2.5);
std::cout << "Area: " << area << std::endl;

2.4.3. Void Functions

A void function does not return a value:

void printMessage(const std::string& message) {
    std::cout << message << std::endl;
}

printMessage("Hello, World!");

2.4.4. Function Overloading

C++ allows you to define multiple functions with the same name but different parameters. This is known as function overloading:

int add(int a, int b) {
    return a + b;
}

double add(double a, double b) {
    return a + b;
}

int sum1 = add(5, 3);       // Calls the int version
double sum2 = add(2.5, 1.5);  // Calls the double version

2.5. Memory Management Basics

Understanding how C++ manages memory is crucial for writing efficient and bug-free programs. C++ supports both static and dynamic memory allocation.

2.5.1. Stack vs. Heap Memory

  • Stack: Memory is allocated and deallocated automatically by the compiler. Variables declared inside functions are typically stored on the stack. Stack memory is fast but limited in size.
  • Heap: Memory is allocated and deallocated manually by the programmer using new and delete. Heap memory is more flexible but requires careful management to avoid memory leaks.

2.5.2. Dynamic Memory Allocation with new and delete

To allocate memory dynamically, use the new operator:

int* ptr = new int;  // Allocates memory for an integer on the heap
*ptr = 42;            // Assigns a value to the allocated memory

To deallocate memory, use the delete operator:

delete ptr;  // Deallocates the memory pointed to by 'ptr'
ptr = nullptr; // avoid dangling pointer

2.5.3. Memory Leaks

A memory leak occurs when dynamically allocated memory is not deallocated, leading to a gradual depletion of available memory. Always ensure that you delete any memory allocated with new.

void allocateMemory() {
    int* ptr = new int;
    // ... (some code)
    delete ptr; // if you comment this delete command, the memory is leaked.
}

By mastering these fundamental C++ concepts, you’ll be well-equipped to tackle more advanced topics such as object-oriented programming, data structures, and algorithms. Visit LEARNS.EDU.VN for more resources and in-depth tutorials to enhance your learning journey.

3. Diving into Object-Oriented Programming (OOP) in C++

Object-oriented programming (OOP) is a programming paradigm that revolves around the concept of “objects,” which contain data (attributes) and code (methods) that operate on that data. C++ fully supports OOP, allowing you to create modular, reusable, and maintainable code. This section covers the core principles of OOP in C++.

3.1. Core Principles of OOP

The four core principles of OOP are:

  • Encapsulation: Bundling data and methods that operate on that data into a single unit (class), and hiding the internal state of the object from the outside world.
  • Abstraction: Simplifying complex reality by modeling classes based on essential characteristics, ignoring unnecessary details.
  • Inheritance: Creating new classes (derived classes) from existing classes (base classes), inheriting their attributes and methods, and extending or modifying their functionality.
  • Polymorphism: The ability of objects of different classes to respond to the same method call in their own way, allowing for flexible and extensible code.

3.2. Classes and Objects

A class is a blueprint for creating objects. It defines the attributes (data members) and methods (member functions) that an object of that class will have.

3.2.1. Defining a Class

To define a class, use the class keyword:

class Dog {
public:
    // Attributes (data members)
    std::string name;
    int age;

    // Methods (member functions)
    void bark() {
        std::cout << "Woof!" << std::endl;
    }
};

3.2.2. Creating Objects

To create an object of a class, use the class name followed by the object name:

Dog myDog;  // Creates an object of the Dog class
myDog.name = "Buddy";
myDog.age = 3;
myDog.bark();  // Output: Woof!

3.2.3. Access Modifiers: public, private, protected

Access modifiers control the visibility of class members:

  • public: Members are accessible from anywhere.
  • private: Members are only accessible from within the class.
  • protected: Members are accessible from within the class and its derived classes.
class BankAccount {
private:
    std::string accountNumber;
    double balance;

public:
    void deposit(double amount) {
        balance += amount;
    }

    double getBalance() const {
        return balance;
    }
};

3.3. Encapsulation and Data Hiding

Encapsulation is the bundling of data and methods that operate on that data, and hiding the internal state of the object from the outside world. This is achieved using access modifiers.

3.3.1. Benefits of Encapsulation

  • Data Protection: Prevents direct access to internal data, ensuring data integrity.
  • Modularity: Simplifies code by grouping related data and methods.
  • Flexibility: Allows internal implementation to be changed without affecting external code.
  • Maintainability: Makes code easier to understand and maintain.

3.3.2. Example of Encapsulation

class Employee {
private:
    std::string name;
    double salary;

public:
    Employee(const std::string& name, double salary) : name(name), salary(salary) {}

    std::string getName() const {
        return name;
    }

    double getSalary() const {
        return salary;
    }

    void setSalary(double salary) {
        if (salary >= 0) {
            this->salary = salary;
        } else {
            std::cout << "Invalid salary." << std::endl;
        }
    }
};

In this example, name and salary are private members, accessible only through the public methods getName, getSalary, and setSalary.

3.4. Abstraction

Abstraction is the process of simplifying complex reality by modeling classes based on essential characteristics, ignoring unnecessary details.

3.4.1. Abstract Classes and Pure Virtual Functions

An abstract class is a class that cannot be instantiated. It contains at least one pure virtual function, which is a virtual function that must be overridden by any derived class.

class Shape {
public:
    // Pure virtual function
    virtual double area() const = 0;

    virtual ~Shape() = default; // Virtual destructor
};

class Circle : public Shape {
private:
    double radius;

public:
    Circle(double radius) : radius(radius) {}

    double area() const override {
        return 3.14159 * radius * radius;
    }
};

In this example, Shape is an abstract class with a pure virtual function area. Circle is a derived class that provides an implementation for area.

3.4.2. Interfaces

An interface is a class with only pure virtual functions. It defines a contract that derived classes must adhere to.

class Printable {
public:
    virtual void print() const = 0;

    virtual ~Printable() = default;
};

class Document : public Printable {
private:
    std::string content;

public:
    Document(const std::string& content) : content(content) {}

    void print() const override {
        std::cout << "Document: " << content << std::endl;
    }
};

3.5. Inheritance

Inheritance is the creation of new classes (derived classes) from existing classes (base classes), inheriting their attributes and methods, and extending or modifying their functionality.

3.5.1. Types of Inheritance

  • Single Inheritance: A class inherits from only one base class.
  • Multiple Inheritance: A class inherits from multiple base classes.
  • Hierarchical Inheritance: Multiple classes inherit from a single base class.
  • Multilevel Inheritance: A class inherits from a derived class, which in turn inherits from another base class.

3.5.2. Example of Inheritance

class Animal {
public:
    void eat() {
        std::cout << "Animal is eating." << std::endl;
    }
};

class Dog : public Animal {
public:
    void bark() {
        std::cout << "Dog is barking." << std::endl;
    }
};

Dog myDog;
myDog.eat();   // Inherited from Animal
myDog.bark();  // Defined in Dog

3.5.3. Virtual Functions and Overriding

Virtual functions allow derived classes to override the behavior of base class functions.

class Animal {
public:
    virtual void makeSound() {
        std::cout << "Animal sound." << std::endl;
    }
};

class Dog : public Animal {
public:
    void makeSound() override {
        std::cout << "Woof!" << std::endl;
    }
};

Animal* animal = new Dog();
animal->makeSound();  // Output: Woof!

3.6. Polymorphism

Polymorphism is the ability of objects of different classes to respond to the same method call in their own way, allowing for flexible and extensible code.

3.6.1. Types of Polymorphism

  • Compile-Time Polymorphism (Static Polymorphism): Achieved through function overloading and operator overloading.
  • Run-Time Polymorphism (Dynamic Polymorphism): Achieved through virtual functions and inheritance.

3.6.2. Example of Polymorphism

class Shape {
public:
    virtual double area() const = 0;
};

class Circle : public Shape {
private:
    double radius;

public:
    Circle(double radius) : radius(radius) {}

    double area() const override {
        return 3.14159 * radius * radius;
    }
};

class Rectangle : public Shape {
private:
    double width;
    double height;

public:
    Rectangle(double width, double height) : width(width), height(height) {}

    double area() const override {
        return width * height;
    }
};

void printArea(const Shape& shape) {
    std::cout << "Area: " << shape.area() << std::endl;
}

Circle circle(5.0);
Rectangle rectangle(4.0, 6.0);

printArea(circle);    // Output: Area: 78.5397
printArea(rectangle); // Output: Area: 24

3.7. Constructors and Destructors

Constructors are special member functions that are called when an object is created. They are used to initialize the object’s attributes. Destructors are special member functions that are called when an object is destroyed. They are used to release any resources held by the object.

3.7.1. Constructors

class MyClass {
private:
    int value;

public:
    // Default constructor
    MyClass() : value(0) {}

    // Parameterized constructor
    MyClass(int value) : value(value) {}

    void printValue() const {
        std::cout << "Value: " << value << std::endl;
    }
};

MyClass obj1;          // Calls the default constructor
MyClass obj2(10);      // Calls the parameterized constructor
obj1.printValue();     // Output: Value: 0
obj2.printValue();     // Output: Value: 10

3.7.2. Destructors

class ResourceHolder {
private:
    int* data;

public:
    ResourceHolder(int size) {
        data = new int[size];
        std::cout << "Resource allocated." << std::endl;
    }

    ~ResourceHolder() {
        delete[] data;
        std::cout << "Resource deallocated." << std::endl;
    }
};

{
    ResourceHolder holder(100);
    // ... (use the resource)
}  // Destructor is called when 'holder' goes out of scope

3.8. Operator Overloading

Operator overloading allows you to redefine the behavior of operators for user-defined types. This can make your code more intuitive and readable.

3.8.1. Overloading Arithmetic Operators

class Complex {
private:
    double real;
    double imaginary;

public:
    Complex(double real, double imaginary) : real(real), imaginary(imaginary) {}

    Complex operator+(const Complex& other) const {
        return Complex(real + other.real, imaginary + other.imaginary);
    }

    void print() const {
        std::cout << real << " + " << imaginary << "i" << std::endl;
    }
};

Complex c1(3.0, 4.0);
Complex c2(1.0, 2.0);
Complex c3 = c1 + c2;  // Calls the overloaded + operator
c3.print();             // Output: 4 + 6i

3.8.2. Overloading Comparison Operators

class Fraction {
private:
    int numerator;
    int denominator;

public:
    Fraction(int numerator, int denominator) : numerator(numerator), denominator(denominator) {}

    bool operator==(const Fraction& other) const {
        return (numerator * other.denominator) == (other.numerator * denominator);
    }
};

Fraction f1(1, 2);
Fraction f2(2, 4);
bool isEqual = (f1 == f2);  // Calls the overloaded == operator
std::cout << "Fractions are equal: " << std::boolalpha << isEqual << std::endl;  // Output: Fractions are equal: true

By mastering object-oriented programming principles in C++, you can create complex, modular, and maintainable software. Visit learns.edu.vn for more in-depth tutorials and resources on C++ programming.

4. Exploring Advanced C++ Features

Once you have a solid understanding of the basics and OOP, you can explore advanced C++ features to enhance your programming skills. This section covers templates, smart pointers, and exception handling.

4.1. Templates

Templates enable you to write generic code that can work with different data types without having to write separate code for each type.

4.1.1. Function Templates

A function template is a function that can operate on different data types.

template <typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}

int maxInt = max(5, 10);         // T is int
double maxDouble = max(2.5, 3.5);  // T is double
std::cout << "Max int: " << maxInt << std::endl;       // Output: Max int: 10
std::cout << "Max double: " << maxDouble << std::endl;  // Output: Max double: 3.5

4.1.2. Class Templates

A class template is a class that can operate on different data types.

template <typename T>
class Stack {
private:
    T* data;
    int size;
    int top;

public:
    Stack(int size) : size(size), top(-1) {
        data = new T[size];
    }

    ~Stack() {
        delete[] data;
    }

    void push(T value) {
        if (top == size - 1) {
            std::cout << "Stack overflow." << std::endl;
            return;
        }
        data[++top] = value;
    }

    T pop() {
        if (top == -1) {
            std::cout << "Stack underflow." << std::endl;
            return T();  // Return a default value
        }
        return data[top--];
    }
};

Stack<int> intStack(5);
intStack.push(10);
intStack.push(20);
std::cout << "Popped int: " << intStack.pop() << std::endl;  // Output: Popped int: 20

Stack<double> doubleStack(5);
doubleStack.push(2.5);
doubleStack.push(3.5);
std::cout << "Popped double: " << doubleStack.pop() << std::endl;  // Output: Popped double: 3.5

4.2. Smart Pointers

Smart pointers are classes that behave like pointers but provide automatic memory management, preventing memory leaks.

4.2.1. std::unique_ptr

std::unique_ptr provides exclusive ownership of a dynamically allocated object. When the unique_ptr goes out of scope, the object is automatically deleted.

#include <memory>

class MyClass {
public:
    MyClass() {
        std::cout << "MyClass created." << std::endl;
    }

    ~MyClass() {
        std::cout << "MyClass destroyed." << std::endl;
    }

    void doSomething() {
        std::cout << "Doing something." << std::endl;
    }
};

{
    std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>();
    ptr->doSomething();  // Output: Doing something.
}  // MyClass is destroyed when ptr goes out of scope

4.2.2. std::shared_ptr

std::shared_ptr allows multiple pointers to share ownership of a dynamically allocated object. The object is deleted when the last shared_ptr pointing to it goes out of scope.

#include <memory>

{
    std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
    std::shared_ptr<MyClass> ptr2 = ptr1;  // Both ptr1 and ptr2 share ownership

    ptr1->doSomething();  // Output: Doing something.
    ptr2->doSomething();  // Output: Doing something.
}  // MyClass is destroyed when both ptr1 and ptr2 go out of scope

4.2.3. std::weak_ptr

std::weak_ptr provides a non-owning reference to an object managed by a shared_ptr. It can be used to check if the object still exists before accessing it.


#include <memory>

{
    std::shared_ptr<MyClass> sharedPtr = std::make_shared<MyClass>();
    std::weak_ptr<MyClass> weakPtr = sharedPtr;

    if (auto ptr = weakPtr.lock

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *