Sobes.tech
Middle

What do you know about smart pointers in C++?

sobes.tech AI

Answer from AI

Smart pointers are RAII wrappers over regular (raw) pointers in C++, providing automatic management of the lifetime of allocated memory, preventing leaks.

Main types of smart pointers in the C++ standard library:

  • std::unique_ptr
  • std::shared_ptr
  • std::weak_ptr

std::unique_ptr

  • Owns the resource exclusively.
  • Cannot be copied, but can be moved.
  • Used for unique ownership of a resource.
  • Minimal overhead, equivalent to a raw pointer.
// unique_ptr example
#include <memory>
#include <iostream>

int main() {
    std::unique_ptr<int> ptr = std::make_unique<int>(10);
    std::cout << *ptr << std::endl; // 10
    // std::unique_ptr<int> ptr2 = ptr; // Compilation error: unique_ptr cannot be copied
    std::unique_ptr<int> ptr3 = std::move(ptr); // Transfer ownership
    std::cout << *ptr3 << std::endl; // 10
    // std::cout << *ptr << std::endl; // Undefined behavior: ptr is now empty
    return 0;
}

std::shared_ptr

  • Allows multiple pointers to share ownership of a resource.
  • Uses a reference count. Memory is freed when the count reaches zero.
  • Can be copied. Each copy increases the reference count.
  • Has higher overhead compared to unique_ptr due to managing the reference count.
// shared_ptr example
#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> ptr1 = std::make_shared<int>(20);
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 1)
    std::shared_ptr<int> ptr2 = ptr1; // Copy, increases use_count
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 2)
    std::shared_ptr<int> ptr3 = ptr1; // Another copy
    std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 3)
    return 0;
}

std::weak_ptr

  • Does not own the resource and does not increase the reference count.
  • Used to solve the problem of cyclic references between shared_ptr.
  • Allows access to the resource pointed to by shared_ptr, but does not prevent its deletion.
  • To access the resource, convert weak_ptr to shared_ptr using the lock() method.
// weak_ptr example
#include <memory>
#include <iostream>

int main() {
    std::shared_ptr<int> shared_ptr_int = std::make_shared<int>(30);
    std::weak_ptr<int> weak_ptr_int = shared_ptr_int;

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl; // 30
    } else {
        std::cout << "Resource has been released." << std::endl;
    }

    shared_ptr_int.reset(); // Resource is released

    if (auto locked_ptr = weak_ptr_int.lock()) {
        std::cout << *locked_ptr << std::endl;
    } else {
        std::cout << "Resource has been released." << std::endl; // Resource has been released.
    }
    return 0;
}

Using smart pointers is considered good practice in modern C++, as it significantly reduces the likelihood of memory management errors.