Как правильно управлять ресурсами и избежать проблем с памятью

Что такое ресурс?
Это то, что вы должны использовать, а затем вернуть тому, кто одолжил вам это. В программировании это может быть дескриптор файла, дескриптор сокета, блокировка мьютекса и т. д.

В C++ стабильность и корректность программного обеспечения сильно зависят от управления ресурсами. Неправильное обращение с ресурсами может привести к утечкам памяти, утечкам файловых дескрипторов или другим утечкам ресурсов.

В этой статье мы проанализируем некоторые советы, взятые из книги Effective C++ Скотта Мейерса [1]».

Совет 1: Оберните ресурс в объекты

Пункт 13.Используйте объекты для управления ресурсами.
Effective C++, Скотт Мейерс, 2005 г.

В C++ настоятельно рекомендуется использовать объекты для управления ресурсами, так как в этом случае используются возможности идиомы RAII (Resource Acquisition Is Initialization).

Идиома RAII — это фундаментальный метод C++, который связывает срок службы объекта с приобретением и высвобождением ресурса. Он использует детерминированное уничтожение объектов C++, чтобы гарантировать надлежащую очистку ресурсов даже при наличии исключений или преждевременных возвратов.

Идея заключается в том, что, инкапсулируя ресурсы в объекты, принцип RAII обеспечивает автоматическое управление ресурсами.

Умные указатели
Лучший способ обернуть ресурсы в объекты в C++ — это умные указатели.

Они инкапсулируют указатель внутри объекта, который обрабатывает получение и освобождение ресурсов с помощью конструкторов и деструкторов.

Два наиболее часто используемых типа интеллектуальных указателей: std::unique_ptr (для монопольного владения) и std::shared_ptr (для совместного владения).

// Managing Dynamic Memory with std::unique_ptr
void processData()
{
    std::unique_ptr<int> ptr(new int(42)); // Acquire resource

    // Perform some operations with the resource
    // ...

    // No need to manually release the resource
    // The unique_ptr's destructor will automatically clean up the memory
}

void useSharedResource()
{
 // Acquire resource
 std::shared_ptr<DatabaseConnection> connection(new DatabaseConnection()); 

    //…