shared_ptr<T>

Последнее обновление: 25.02.2023

Тип 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
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850