std::shared_ptr::reset — cppreference.com
Материал из cppreference.com
<tbody> </tbody>
|
|
(1) | (начиная с C++11) |
|
|
(2) | (начиная с C++11) |
|
|
(3) | (начиная с C++11) |
|
|
(4) | (начиная с C++11) |
Заменяет управляемый объект объектом, на который указывает ptr. Можно указать необязательное средство удаления d, которое позже используется для уничтожения нового объекта, когда им не владеет ни один объект shared_ptr. По умолчанию в качестве средства удаления используется выражение delete. Всегда выбирается правильное выражение delete, соответствующее предоставленному типу, поэтому функция реализована в виде шаблона с использованием отдельного параметра Y.
Если *this уже владеет объектом, и это последний shared_ptr, владеющий им, объект уничтожается с помощью принадлежащего средства удаления.
Если объект, на который указывает ptr, уже принадлежит, функция обычно приводит к неопределённому поведению.
1) Освобождает владение управляемым объектом, если таковой имеется. После вызова *this не управляет никаким объектом. Эквивалентно shared_ptr().swap(*this);
2-4) Заменяет управляемый объект объектом, на который указывает ptr. Y должен быть полным типом и неявно преобразовываться в T. Кроме того:
2) Использует выражение delete в качестве средства удаления. Должно быть доступно действительное выражение delete, т.е. delete ptr должно быть корректно, иметь чётко определённое поведение и не вызывать никаких исключений. Эквивалентно shared_ptr<T>(ptr).swap(*this);.
3) Использует указанное средство удаления d в качестве средства удаления. Deleter должен вызываться для типа T, т.е. d(ptr) должен быть корректным, иметь чётко определённое поведение и не вызывать никаких исключений. Deleter должен быть CopyConstructible, а его конструктор копирования и деструктор не должны генерировать исключения. Эквивалентно shared_ptr<T>(ptr, d).swap(*this);.
4) То же, что и (3), но дополнительно использует копию alloc для выделения данных для внутреннего использования. Alloc должен быть Allocator. Конструктор копирования и деструктор не должны генерировать исключения. Эквивалентно shared_ptr<T>(ptr, d, alloc).swap(*this);.
Параметры
| ptr | — | указатель на объект, для которого нужно получить право собственности |
| d | — | средство удаления для удаления объекта |
| alloc | — | аллокатор, используемый для внутренних распределений |
Возвращаемое значение
(нет)
Исключения
2) std::bad_alloc, если требуемая дополнительная память не может быть получена. Может генерировать определяемое реализацией исключение для других ошибок. Вызывается delete ptr, если возникает исключение.
3,4) std::bad_alloc, если требуемая дополнительная память не может быть получена. Может генерировать определяемое реализацией исключение для других ошибок. Вызывается d(ptr), если возникает исключение.
Пример
#include <memory> #include <iostream> struct Foo { Foo(int n = 0) noexcept : bar(n) { std::cout << "Foo::Foo(), bar = " << bar << " @ " << this << '\n'; } ~Foo() { std::cout << "Foo::~Foo(), bar = " << bar << " @ " << this << '\n'; } int getBar() const noexcept { return bar; } private: int bar; }; int main() { std::cout << "1) уникальное владение\n"; { std::shared_ptr<Foo> sptr = std::make_shared<Foo>(100); std::cout << "Foo::bar = " << sptr->getBar() << ", use_count() = " << sptr.use_count() << '\n'; // Сбрасываем shared_ptr, не передавая ему новый экземпляр Foo. // Старый экземпляр будет уничтожен после этого вызова. std::cout << "вызов sptr.reset()...\n"; sptr.reset(); // здесь вызывает деструктор Foo std::cout << "После reset(): use_count() = " << sptr.use_count() << ", sptr = " << sptr << '\n'; } // Нет вызова деструктора Foo, это было сделано ранее в reset(). std::cout << "\n2) уникальное владение\n"; { std::shared_ptr<Foo> sptr = std::make_shared<Foo>(200); std::cout << "Foo::bar = " << sptr->getBar() << ", use_count() = " << sptr.use_count() << '\n'; // Сбрасываем shared_ptr, передавая ему новый экземпляр Foo. // Старый экземпляр будет уничтожен после этого вызова. std::cout << "вызов sptr.reset()...\n"; sptr.reset(new Foo{222}); std::cout << "После reset(): use_count() = " << sptr.use_count() << ", sptr = " << sptr << "\nВыход из области видимости...\n"; } // Вызывается деструктор Foo. std::cout << "\n3) множественное владение\n"; { std::shared_ptr<Foo> sptr1 = std::make_shared<Foo>(300); std::shared_ptr<Foo> sptr2 = sptr1; std::shared_ptr<Foo> sptr3 = sptr2; std::cout << "Foo::bar = " << sptr1->getBar() << ", use_count() = " << sptr1.use_count() << '\n'; // Сбрасываем shared_ptr sptr1, передавая ему новый экземпляр Foo. // Старый экземпляр останется общим для sptr2 и sptr3. std::cout << "вызов sptr1.reset()...\n"; sptr1.reset(new Foo{333}); std::cout << "После reset():\n" << "sptr1.use_count() = " << sptr1.use_count() << ", sptr1 @ " << sptr1 << '\n' << "sptr2.use_count() = " << sptr2.use_count() << ", sptr2 @ " << sptr2 << '\n' << "sptr3.use_count() = " << sptr3.use_count() << ", sptr3 @ " << sptr3 << '\n' << "Выход из области видимости...\n"; } // Вызывает два деструктора: 1) Foo, принадлежащего sptr1, // 2) Foo, разделяемого между sptr2/sptr3. }
Возможный вывод:
1) уникальное владение Foo::Foo(), bar = 100 @ 0x23c5040 Foo::bar = 100, use_count() = 1 вызов sptr.reset()... Foo::~Foo(), bar = 100 @ 0x23c5040 После reset(): use_count() = 0, sptr = 0 2) уникальное владение Foo::Foo(), bar = 200 @ 0x23c5040 Foo::bar = 200, use_count() = 1 вызов sptr.reset()... Foo::Foo(), bar = 222 @ 0x23c5050 Foo::~Foo(), bar = 200 @ 0x23c5040 После reset(): use_count() = 1, sptr = 0x23c5050 Выход из области видимости... Foo::~Foo(), bar = 222 @ 0x23c5050 3) множественное владение Foo::Foo(), bar = 300 @ 0x23c5080 Foo::bar = 300, use_count() = 3 вызов sptr1.reset()... Foo::Foo(), bar = 333 @ 0x23c5050 После reset(): sptr1.use_count() = 1, sptr1 @ 0x23c5050 sptr2.use_count() = 2, sptr2 @ 0x23c5080 sptr3.use_count() = 2, sptr3 @ 0x23c5080 Выход из области видимости... Foo::~Foo(), bar = 300 @ 0x23c5080 Foo::~Foo(), bar = 333 @ 0x23c5050