Middle
Какво знаете за умните указатели в C++?
sobes.tech AI
Отговор от AI
Умни указатели - това са RAII-обвивки над обикновени (сурови) указатели в C++, които предоставят автоматично управление на жизнения цикъл на заделената памет, предотвратявайки течове.
Основните типове умни указатели в стандартната библиотека на C++:
std::unique_ptrstd::shared_ptrstd::weak_ptr
std::unique_ptr
- Владее ресурс ексклузивно.
- Не може да бъде копиран, но може да бъде преместван.
- Използва се за уникално владение на ресурс.
- Разходите са минимални, еквивалентни на суров указател.
// пример с unique_ptr
#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; // Неопределено поведение: ptr сега е празен
return 0;
}
std::shared_ptr
- Позволява на множество указатели да притежават един ресурс.
- Използва брояч на препратки. Паметта се освобождава, когато броячът стане нула.
- Може да бъде копиран. Всяко копие увеличава брояча.
- Има по-високи разходи в сравнение с
unique_ptrпоради управлението на брояча.
// пример с shared_ptr
#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
#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 << "Ресурсът вече е освободен." << std::endl;
}
shared_ptr_int.reset(); // Ресурсът се освобождава
if (auto locked_ptr = weak_ptr_int.lock()) {
std::cout << *locked_ptr << std::endl;
} else {
std::cout << "Ресурсът вече е освободен." << std::endl; // Ресурсът е освободен
}
return 0;
}
Използването на умни указатели е добра практика в съвременния C++, тъй като значително намалява вероятността от грешки при управлението на паметта.