Назад к вопросам
Middle
98
questionbank
Что вы знаете об умных указателях в C++?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Умные указатели - это RAII-обертки над обычными (сырыми) указателями в C++, предоставляющие автоматическое управление временем жизни выделенной памяти, предотвращая утечки.
Основные типы умных указателей в стандартной библиотеке C++:
std::unique_ptrstd::shared_ptrstd::weak_ptr
std::unique_ptr
- Владеет ресурсом эксклюзивно.
- Не может быть скопирован, но может быть перемещен.
- Используется для уникального владения ресурсом.
- Накладные расходы минимальны, эквивалентны сырому указателю.
// 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; // Ошибка компиляции: unique_ptr не копируется
std::unique_ptr<int> ptr3 = std::move(ptr); // Перемещение владения
std::cout << *ptr3 << std::endl; // 10
// std::cout << *ptr << std::endl; // Undefined behavior: ptr теперь пустой
return 0;
}
std::shared_ptr
- Позволяет множеству указателей совместно владеть одним ресурсом.
- Использует счетчик ссылок (reference count). Память освобождается, когда счетчик ссылок становится равен нулю.
- Может быть скопирован. Каждая копия увеличивает счетчик ссылок.
- Имеет более высокие накладные расходы по сравнению с
unique_ptrиз-за необходимости обслуживать счетчик ссылок.
// 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; // Копирование, увеличивает use_count
std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 2)
std::shared_ptr<int> ptr3 = ptr1; // Еще одна копия
std::cout << *ptr1 << " (use_count: " << ptr1.use_count() << ")" << std::endl; // 20 (use_count: 3)
return 0;
}
std::weak_ptr
- Не владеет ресурсом и не увеличивает счетчик ссылок.
- Используется для решения проблемы цикличных ссылок между
shared_ptr. - Позволяет получить доступ к ресурсу, на который указывает
shared_ptr, но не предотвращает его удаление. - Для доступа к ресурсу необходимо преобразовать
weak_ptrвshared_ptrс помощью методаlock().
// 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(); // Ресурс освобождается
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;
}
Использование умных указателей является хорошей практикой в современном C++, так как значительно снижает вероятность ошибок управления памятью.