Тип shared_ptr<T> применяется для создания указателей на объекты, на которые может указывать несколько указателей.
shared_ptr<T> позволяет создавать множество объектов shared_ptr<T>
, которые содержат один и тот же адрес.
Для данных указателей применяется механизм подсчета ссылок (reference counting). Каждый раз, когда создается объект shared_ptr<T>
, увеличивается счетчик объектов
shared_ptr<T>
, которые содержат определенный адрес. Когда объект shared_ptr<T>
удаляется или ему присваивается другой адрес,
счетчик ссылок уменьшается на единицу. Когда больше нет объектов shared_ptr<T>
, которые ссылаются на определенный адрес, счетчик ссылок сбрасывается в ноль.
При определении указателя без явной инициализации по умолчанию он инициализируется значением nullptr
std::shared_ptr<int> ptr; // ptr = nullptr
Для инициализации конкретным значением можно применять функцию std::make_shared<T>
std::shared_ptr<int> ptr {std::make_shared<int>(22)};
Далее через указатель shared_ptr
можно также, как и через обычный указатель, получать и изменять динамический объект:
#include <iostream> #include <memory> int main() { std::shared_ptr<int> ptr {std::make_shared<int>(22)}; std::cout << "address: " << ptr << std::endl; // address: 0x1e004671260 std::cout << "old value: " << *ptr << std::endl; // old value: 22 *ptr = 33; // меняем значение std::cout << "new value: " << *ptr << std::endl; // new value: 33 }
Также можно инициализировать указатель shared_ptr
другим указателем shared_ptr
. В этом случае они будут хранить один и тот же адрес:
#include <iostream> #include <memory> int main() { std::shared_ptr<int> ptr1 {std::make_shared<int>(22)}; std::shared_ptr<int> ptr2 {ptr1}; // ptr2 ссылается на тот же объект, что и ptr1 std::cout << "ptr1 address: " << ptr1 << std::endl; std::cout << "ptr1 value: " << *ptr1 << std::endl; std::cout << "ptr2 address: " << ptr2 << std::endl; std::cout << "ptr2 value: " << *ptr2 << std::endl; }
Пример консольного вывода:
ptr1 address: 0x15fbbf81020 ptr1 value: 22 ptr2 address: 0x15fbbf81020 ptr2 value: 22
Начиная со стандарта C++20 указатель shared_ptr
может указывать на массив:
unsigned n{5}; // размер массива auto pnumbers { std::make_shared<int[]>(n) }; // массив из n элементов, равных 0
В данном случае указать pnumbers указывает на массив из 5 элементов. При этом все эти элементы уже инициализированы значениями по умолчанию (для примитивных типов - числом 0).
С помощью квадратных скобок можно обращаться к определенным элементам массива:
#include <iostream> #include <memory> int main() { unsigned n{5}; // размер массива auto pnumbers { std::make_shared<int[]>(n) }; // массив {0, 0, 0, 0, 0} std::cout << "pnumbers[1] initial value: " << pnumbers[1] << std::endl; // pnumbers[1] initial value: 0 pnumbers[1] = 121; // изменяем значение std::cout << "pnumbers[1] new value: " << pnumbers[1] << std::endl; // pnumbers[1] new value: 121 }
Можно пройтись по массиву в цикле
#include <iostream> #include <memory> int main() { unsigned n{5}; // размер массива auto pnumbers { std::make_shared<int[]>(n) }; // массив из n элементов // изменим и выведем все элементы на консоль for (unsigned i {}; i < n; i++) { pnumbers[i] = i+1; std::cout << "pnumbers[" << i <<"] = " << pnumbers[i] << std::endl; } }
Консольный вывод:
pnumbers[0] = 1 pnumbers[1] = 2 pnumbers[2] = 3 pnumbers[3] = 4 pnumbers[4] = 5