Поделиться через


Класс shared_ptr

Помещает объект с динамическим выделением памяти в оболочку интеллектуального указателя с подсчитанными ссылками.

Синтаксис

template <class T>
class shared_ptr;

Замечания

Класс shared_ptr описывает объект, использующий подсчет ссылок для управления ресурсами. Объект shared_ptr фактически содержит указатель на ресурс, которым он владеет, или содержит пустой указатель (NULL). Обладать ресурсом могут несколько объектов shared_ptr; при удалении последнего объекта shared_ptr, обладающего тем или иным ресурсом, данный ресурс освобождается.

При shared_ptr переназначении или сбросе ресурса прекращается владение ресурсом.

Аргумент шаблона T может быть неполным типом, за исключением случаев, особо отмеченных для определенных функций-членов.

При создании объекта shared_ptr<T> из указателя ресурса типа G* или из shared_ptr<G> тип указателя G* должен допускать преобразование в T*. Если он не преобразуется, код не будет компилироваться. Например:

#include <memory>
using namespace std;

class F {};
class G : public F {};

shared_ptr<G> sp0(new G);   // okay, template parameter G and argument G*
shared_ptr<G> sp1(sp0);     // okay, template parameter G and argument shared_ptr<G>
shared_ptr<F> sp2(new G);   // okay, G* convertible to F*
shared_ptr<F> sp3(sp0);     // okay, template parameter F and argument shared_ptr<G>
shared_ptr<F> sp4(sp2);     // okay, template parameter F and argument shared_ptr<F>
shared_ptr<int> sp5(new G); // error, G* not convertible to int*
shared_ptr<int> sp6(sp2);   // error, template parameter int and argument shared_ptr<F>

Объект shared_ptr владеет ресурсом:

  • если он был создан с использованием указателя на этот ресурс;

  • если он был создан из объекта shared_ptr, владеющего этим ресурсом;

  • Значение weak_ptr /gt;, если оно было создано из объекта, указывающего на этот ресурс, или

  • Значение shared_ptr::operator= помощью вызова функции-члена shared_ptr::reset.

Владеющие ресурсом объекты shared_ptr совместно используют один блок управления. Блок управления содержит следующее:

  • количество объектов shared_ptr, владеющих ресурсом;

  • количество объектов weak_ptr, указывающих на ресурс;

  • метод удаления для этого ресурса, если он есть;

  • пользовательский распределитель для блока управления, если он есть.

Объект shared_ptr , инициализированный с помощью указателя NULL, имеет блок управления и не пуст. После того как объект shared_ptr освобождает ресурс, он перестает быть его владельцем. После того как объект weak_ptr освобождает ресурс, он перестает указывать на него.

Если количество объектов shared_ptr, владеющих ресурсом, становится равным нулю, ресурс освобождается путем удаления или передачи его адреса в метод удаления в зависимости от того, как изначально был создан владелец ресурса. Если количество объектов shared_ptr, владеющих ресурсом, как и число объектов weak_ptr, которые указывают на ресурс, становится равным нулю, освобождается блок управления с использованием пользовательского распределителя этого блока управления при его наличии.

Пустой shared_ptr объект не владеет ресурсами и не имеет блока управления.

Метод удаления является объектом функции, имеющим функцию-член operator(). Его тип должен быть конструируемым по копии, а его конструктор копии и деструктор не должны выдавать исключения. Он принимает один параметр — удаляемый объект.

Некоторые функции принимают список аргументов, определяющий свойства результирующего объекта shared_ptr<T> или weak_ptr<T>. Такой список аргументов можно задать несколькими способами.

нет аргументов: результирующий объект является пустым shared_ptr объектом или пустым weak_ptr объектом.

ptr: указатель типа Other* на управляемый ресурс. T должен быть полным типом. Если функция завершается ошибкой (так как блок управления не может быть выделен), она вычисляет выражение delete ptr.

ptr, deleter: указатель типа Other* на управляемый ресурс и средство удаления для этого ресурса. Если функция завершается сбоем (так как блок управления не может быть выделен), он вызывает deleter(ptr)вызовы, которые должны быть четко определены.

ptr, deleter, alloc: указатель типа Other* на управляемый ресурс, удаленный для этого ресурса и распределитель для управления любым хранилищем, которое должно быть выделено и освобождено. Если функция завершается сбоем (так как блок управления не может быть выделен), он вызывает deleter(ptr)вызовы, которые должны быть четко определены.

spshared_ptr<Other>: объект, принадлежащий управляемому ресурсу.

wp: объект, указывающий weak_ptr<Other> на управляемый ресурс.

apauto_ptr<Other>: объект, содержащий указатель на управляемый ресурс. Если функция выполнена успешно, она вызывается ap.release(); в противном случае она остается ap без изменений.

Во всех случаях тип указателя типа Other* должен допускать преобразование в T*.

Потокобезопасность

Несколько потоков могут одновременно считывать и записывать разные объекты shared_ptr, даже если они являются копиями с общим владельцем.

Участники

Имя Описание
Конструкторы
shared_ptr Создает документ shared_ptr.
~shared_ptr Удаляет shared_ptr.
Typedefs
element_type Тип элемента.
weak_type Тип слабого указателя на элемент.
Функции-члены
get Возвращает адрес принадлежащего ресурса.
owner_before Возвращает значение true, если shared_ptr упорядочен до (меньше) предоставленного указателя.
reset Заменяет принадлежащий ресурс.
swap Меняет местами два объекта shared_ptr.
unique Проверяет, является ли принадлежащий ресурс уникальным.
use_count Подсчитывает количество владельцев ресурса.
Операторы
operator bool Проверяет существование принадлежащего ресурса.
operator* Возвращает указанное значение.
operator= Заменяет принадлежащий ресурс.
operator-> Получает указатель на указанное значение.

element_type

Тип элемента.

typedef T element_type;                  // before C++17
using element_type = remove_extent_t<T>; // C++17

Замечания

Тип element_type является синонимом для параметра Tшаблона.

Пример

// std__memory__shared_ptr_element_type.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp0(new int(5));
    std::shared_ptr<int>::element_type val = *sp0;

    std::cout << "*sp0 == " << val << std::endl;

    return (0);
}
*sp0 == 5

get

Возвращает адрес принадлежащего ресурса.

element_type* get() const noexcept;

Замечания

Функция-член возвращает адрес контролируемого ресурса. Если объект не владеет ресурсом, он возвращает значение 0.

Пример

// std__memory__shared_ptr_get.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp0;
    std::shared_ptr<int> sp1(new int(5));

    std::cout << "sp0.get() == 0 == " << std::boolalpha
        << (sp0.get() == 0) << std::endl;
    std::cout << "*sp1.get() == " << *sp1.get() << std::endl;

    return (0);
}
sp0.get() == 0 == true
*sp1.get() == 5

operator bool

Проверяет существование принадлежащего ресурса.

explicit operator bool() const noexcept;

Замечания

Оператор возвращает значение true , в get() != nullptrпротивном случае false.

Пример

// std__memory__shared_ptr_operator_bool.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp0;
    std::shared_ptr<int> sp1(new int(5));

    std::cout << "(bool)sp0 == " << std::boolalpha
        << (bool)sp0 << std::endl;
    std::cout << "(bool)sp1 == " << std::boolalpha
        << (bool)sp1 << std::endl;

    return (0);
}
(bool)sp0 == false
(bool)sp1 == true

operator*

Возвращает указанное значение.

T& operator*() const noexcept;

Замечания

Оператор косвенного обращения возвращает *get(). Следовательно, сохраненный указатель не должен быть пустым.

Пример

// std__memory__shared_ptr_operator_st.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp0(new int(5));

    std::cout << "*sp0 == " << *sp0 << std::endl;

    return (0);
}
*sp0 == 5

operator=

Заменяет принадлежащий ресурс.

shared_ptr& operator=(const shared_ptr& sp) noexcept;

shared_ptr& operator=(shared_ptr&& sp) noexcept;

template <class Other>
shared_ptr& operator=(const shared_ptr<Other>& sp) noexcept;

template <class Other>
shared_ptr& operator=(shared_ptr<Other>&& sp) noexcept;

template <class Other>
shared_ptr& operator=(auto_ptr<Other>&& ap);    // deprecated in C++11, removed in C++17

template <class Other, class Deleter>
shared_ptr& operator=(unique_ptr<Other, Deleter>&& up);

Параметры

sp
Общий указатель для копирования или перемещения.

ap
Автоматический указатель для перемещения. Перегрузка auto_ptr устарела в C++11 и удалена в C++17.

up
Уникальный указатель на объект для принятия права владения. up не владеет объектом после вызова.

Other
Тип объекта, на который указывает sp, apили up.

Deleter
Тип удаленного объекта, хранящегося для последующего удаления объекта.

Замечания

Все операторы уменьшают значение счетчика ссылок для ресурса, который в настоящее время контролируется *this, и передают владение ресурсом, указанным последовательностью операндов, объекту *this. Если число ссылок на ресурс становится равным нулю, ресурс освобождается (delete). Если оператор завершается ошибкой, он остается *this неизменным.

Пример

// std__memory__shared_ptr_operator_as.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp0;
    std::shared_ptr<int> sp1(new int(5));
    std::unique_ptr<int> up(new int(10));

    sp0 = sp1;
    std::cout << "*sp0 == " << *sp0 << std::endl;

    sp0 = up;
    std::cout << "*sp0 == " << *sp0 << std::endl;

    return (0);
}
*sp0 == 5
*sp0 == 10

operator->

Получает указатель на указанное значение.

T* operator->() const noexcept;

Замечания

Оператор выбора возвращает get(), так что выражение sp->member ведет себя так же, как (sp.get())->member, где sp — это объект класса shared_ptr<T>. Следовательно, сохраненный указатель не должен быть пустым, и T должен быть классом, структурой или типом объединения с членом member.

Пример

// std__memory__shared_ptr_operator_ar.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

typedef std::pair<int, int> Mypair;
int main()
{
    std::shared_ptr<Mypair> sp0(new Mypair(1, 2));

    std::cout << "sp0->first == " << sp0->first << std::endl;
    std::cout << "sp0->second == " << sp0->second << std::endl;

    return (0);
}
sp0->first == 1
sp0->second == 2

owner_before

Возвращает значение true, если shared_ptr упорядочен до (меньше) предоставленного указателя.

template <class Other>
bool owner_before(const shared_ptr<Other>& ptr) const noexcept;

template <class Other>
bool owner_before(const weak_ptr<Other>& ptr) const noexcept;

Параметры

ptr
Ссылка на lvalue либо a shared_ptr , либо a weak_ptr.

Замечания

Функция-член шаблона возвращает значение true, если *this он упорядочен до ptr.

reset

Заменяет принадлежащий ресурс.

void reset() noexcept;

template <class Other>
void reset(Other *ptr);

template <class Other, class Deleter>
void reset(
    Other *ptr,
    Deleter deleter);

template <class Other, class Deleter, class Allocator>
void reset(
    Other *ptr,
    Deleter deleter,
    Allocator alloc);

Параметры

Other
Тип, управляемый указателем аргумента.

Deleter
Тип метода удаления.

ptr
Копируемый указатель.

deleter
Метод удаления для копирования.

Allocator
Тип распределителя.

alloc
Распределитель для копирования.

Замечания

Все операторы уменьшают значение счетчика ссылок для ресурса, который в настоящее время контролируется *this, и передают владение ресурсом, указанным последовательностью операндов, объекту *this. Если число ссылок на ресурс становится равным нулю, ресурс освобождается (delete). Если оператор завершается ошибкой, он остается *this неизменным.

Пример

// std__memory__shared_ptr_reset.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

struct deleter
{
    void operator()(int *p)
    {
        delete p;
    }
};

int main()
{
    std::shared_ptr<int> sp(new int(5));

    std::cout << "*sp == " << std::boolalpha
        << *sp << std::endl;

    sp.reset();
    std::cout << "(bool)sp == " << std::boolalpha
        << (bool)sp << std::endl;

    sp.reset(new int(10));
    std::cout << "*sp == " << std::boolalpha
        << *sp << std::endl;

    sp.reset(new int(15), deleter());
    std::cout << "*sp == " << std::boolalpha
        << *sp << std::endl;

    return (0);
}
*sp == 5
(bool)sp == false
*sp == 10
*sp == 15

shared_ptr

Создает документ shared_ptr.

constexpr shared_ptr() noexcept;

constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() {}

shared_ptr(const shared_ptr& sp) noexcept;

shared_ptr(shared_ptr&& sp) noexcept;

template <class Other>
explicit shared_ptr(Other* ptr);

template <class Other, class Deleter>
shared_ptr(
    Other* ptr,
    Deleter deleter);

template <class Deleter>
shared_ptr(
    nullptr_t ptr,
    Deleter deleter);

template <class Other, class Deleter, class Allocator>
shared_ptr(
    Other* ptr,
    Deleter deleter,
    Allocator alloc);

template <class Deleter, class Allocator>
shared_ptr(
    nullptr_t ptr,
    Deleter deleter,
    Allocator alloc);

template <class Other>
shared_ptr(
    const shared_ptr<Other>& sp) noexcept;

template <class Other>
explicit shared_ptr(
    const weak_ptr<Other>& wp);

template <class &>
shared_ptr(
    std::auto_ptr<Other>& ap);

template <class &>
shared_ptr(
    std::auto_ptr<Other>&& ap);

template <class Other, class Deleter>
shared_ptr(
    unique_ptr<Other, Deleter>&& up);

template <class Other>
shared_ptr(
    const shared_ptr<Other>& sp,
    element_type* ptr) noexcept;

template <class Other>
shared_ptr(
    shared_ptr<Other>&& sp,
    element_type* ptr) noexcept;

template <class Other, class Deleter>
shared_ptr(
    const unique_ptr<Other, Deleter>& up) = delete;

Параметры

Other
Тип, управляемый указателем аргумента.

ptr
Копируемый указатель.

Deleter
Тип метода удаления.

Allocator
Тип распределителя.

deleter
Метод удаления.

alloc
Распределитель.

sp
Интеллектуальный указатель для копирования

wp
Слабый указатель.

ap
"Автоматический" указатель ( auto_ptr ) для копирования

Замечания

Каждый из конструкторов создает объект для контроля над ресурсом, указанным в качестве операнда. Конструктор shared_ptr(const weak_ptr<Other>& wp) создает объект исключения типа bad_weak_ptr , если wp.expired().

Пример

// std__memory__shared_ptr_construct.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

struct deleter
{
    void operator()(int *p)
    {
        delete p;
    }
};

int main()
{
    std::shared_ptr<int> sp0;
    std::cout << "(bool)sp0 == " << std::boolalpha
        << (bool)sp0 << std::endl;

    std::shared_ptr<int> sp1(new int(5));
    std::cout << "*sp1 == " << *sp1 << std::endl;

    std::shared_ptr<int> sp2(new int(10), deleter());
    std::cout << "*sp2 == " << *sp2 << std::endl;

    std::shared_ptr<int> sp3(sp2);
    std::cout << "*sp3 == " << *sp3 << std::endl;

    std::weak_ptr<int> wp(sp3);
    std::shared_ptr<int> sp4(wp);
    std::cout << "*sp4 == " << *sp4 << std::endl;

    std::auto_ptr<int> ap(new int(15));
    std::shared_ptr<int> sp5(ap);
    std::cout << "*sp5 == " << *sp5 << std::endl;

    return (0);
}
(bool)sp0 == false
*sp1 == 5
*sp2 == 10
*sp3 == 10
*sp4 == 10
*sp5 == 15

~shared_ptr

Удаляет shared_ptr.

~shared_ptr();

Замечания

Деструктор уменьшает значение счетчика ссылок для ресурса, который в настоящее время контролируется *this. Если число ссылок на ресурс становится равным нулю, ресурс освобождается (delete).

Пример

// std__memory__shared_ptr_destroy.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp1(new int(5));
    std::cout << "*sp1 == " << *sp1 << std::endl;
    std::cout << "use count == " << sp1.use_count() << std::endl;

    {
        std::shared_ptr<int> sp2(sp1);
        std::cout << "*sp2 == " << *sp2 << std::endl;
        std::cout << "use count == " << sp1.use_count() << std::endl;
    }

    // check use count after sp2 is destroyed
    std::cout << "use count == " << sp1.use_count() << std::endl;

    return (0);
}
*sp1 == 5
use count == 1
*sp2 == 5
use count == 2
use count == 1

swap

Меняет местами два объекта shared_ptr.

void swap(shared_ptr& sp) noexcept;

Параметры

sp
Разделяемый указатель (shared_ptr), с которым требуется произвести обмен контролируемыми объектами.

Замечания

Функция-член устанавливает контроль sp над ресурсом, изначально контролируемым *this и контроль sp над ресурсом, изначально контролируемым *this. Функция не изменяет количество ссылок для двух ресурсов и не создает никаких исключений.

Пример

// std__memory__shared_ptr_swap.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp1(new int(5));
    std::shared_ptr<int> sp2(new int(10));
    std::cout << "*sp1 == " << *sp1 << std::endl;

    sp1.swap(sp2);
    std::cout << "*sp1 == " << *sp1 << std::endl;

    swap(sp1, sp2);
    std::cout << "*sp1 == " << *sp1 << std::endl;
    std::cout << std::endl;

    std::weak_ptr<int> wp1(sp1);
    std::weak_ptr<int> wp2(sp2);
    std::cout << "*wp1 == " << *wp1.lock() << std::endl;

    wp1.swap(wp2);
    std::cout << "*wp1 == " << *wp1.lock() << std::endl;

    swap(wp1, wp2);
    std::cout << "*wp1 == " << *wp1.lock() << std::endl;

    return (0);
}
*sp1 == 5
*sp1 == 10
*sp1 == 5
*wp1 == 5
*wp1 == 10
*wp1 == 5

unique

Проверяет, является ли принадлежащий ресурс уникальным. Эта функция устарела в C++17 и удалена в C++20.

bool unique() const noexcept;

Замечания

Функция-член возвращает значение true, если никакой другой объект shared_ptr не контролирует ресурс, контролируемый *this; в противном случае — значение false.

Пример

// std__memory__shared_ptr_unique.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp1(new int(5));
    std::cout << "sp1.unique() == " << std::boolalpha
        << sp1.unique() << std::endl;

    std::shared_ptr<int> sp2(sp1);
    std::cout << "sp1.unique() == " << std::boolalpha
        << sp1.unique() << std::endl;

    return (0);
}
sp1.unique() == true
sp1.unique() == false

use_count

Подсчитывает количество владельцев ресурса.

long use_count() const noexcept;

Замечания

Функция-член возвращает число объектов shared_ptr, контролирующих ресурс, который контролируется *this.

Пример

// std__memory__shared_ptr_use_count.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>

int main()
{
    std::shared_ptr<int> sp1(new int(5));
    std::cout << "sp1.use_count() == "
        << sp1.use_count() << std::endl;

    std::shared_ptr<int> sp2(sp1);
    std::cout << "sp1.use_count() == "
        << sp1.use_count() << std::endl;

    return (0);
}
sp1.use_count() == 1
sp1.use_count() == 2

weak_type

Тип слабого указателя на элемент.

using weak_type = weak_ptr<T>; // C++17

Замечания

Определение weak_type было добавлено в C++17.

См. также

Справочник по файлам заголовков
<memory>
unique_ptr
Класс weak_ptr