在线文档教程
C++
应用 | Utilities

std::shared_ptr

STD::共享[医]PTR

Defined in header
template< class T > class shared_ptr;(since C++11)

std::shared_ptr是通过指针保留对象共享所有权的智能指针。几个shared_ptr对象可以拥有相同的对象。当发生下列任何一种情况时,该对象将被销毁,其内存将被释放:

  • 最后的余生shared_ptr拥有物品被销毁;

  • 最后的余生shared_ptr拥有该对象将通过以下方式分配另一个指针operator=reset()...

使用delete-expression或自定义删除器提供给shared_ptr在建筑过程中。

shared_ptr可以在存储指向另一个对象的指针时共享对象的所有权。此功能可用于在拥有成员对象所属对象时指向成员对象。存储的指针是get()、取消引用和比较操作符。托管指针是在使用计数达到零时传递给删除器的指针。

shared_ptr也不可能拥有任何对象,在这种情况下,它被调用。空空%28 a空共享[医]如果使用别名构造函数来创建%29,则PTR可能有一个非空存储指针。

所有的专门化shared_ptr满足…的要求CopyConstructible,,,CopyAssignable,和LessThanComparable而且是上下文可转换到bool...

所有成员函数%28,包括复制构造函数和副本分配%29,可以由多个线程在shared_ptr即使这些实例是同一个对象的副本和共享所有权,也不需要额外的同步。如果多个执行线程访问相同的shared_ptr没有同步的情况下,任何这些访问都使用非const成员函数。shared_ptr则会发生数据竞争;共享[医]原子函数的PTR过载可用于防止数据竞争。

成员类型

Member typeDefinition
element_typeT (until C++17) std::remove_extent_t<T> (since C++17)
T(until C++17)
std::remove_extent_t<T>(since C++17)
weak_type (since C++17)std::weak_ptr<T>

成员函数

(constructor)constructs new shared_ptr (public member function)
(destructor)destructs the owned object if no more shared_ptrs link to it (public member function)
operator=assigns the shared_ptr (public member function)

修饰符

重置替换托管对象%28公共成员函数%29

交换托管对象%28公共成员函数%29

观察员

GET返回存储的指针%28公共成员函数%29

操作者%2A运算符->取消存储的指针%28公共成员函数%29

操作者提供对存储的数组%28公共成员函数%29的索引访问

使用[医]计数返回共享的数目。[医]引用同一个托管对象%28公共成员函数%29的PTR对象

唯一%28不推荐%29检查托管对象是否仅由当前共享管理[医]PTR实例%28公共成员函数%29

操作符bool检查存储的指针是否为空%28公共成员函数%29。

业主[医]提供共享指针%28公共成员函数%29的基于所有者的排序。

非会员职能

make_sharedcreates a shared pointer that manages a new object (function template)
allocate_sharedcreates a shared pointer that manages a new object allocated using an allocator (function template)
static_pointer_castdynamic_pointer_castconst_pointer_castreinterpret_pointer_cast (C++17)applies static_cast, dynamic_cast, const_cast, or reinterpret_cast to the stored pointer (function template)
get_deleterreturns the deleter of specified type, if owned (function template)
operator==operator!=operator<operator<=operator>operator>=compares with another shared_ptr or with nullptr (function template)
operator<<outputs the value of the stored pointer to an output stream (function template)
std::swap(std::shared_ptr) (C++11)specializes the std::swap algorithm (function template)

std::atomic_is_lock_free(std::shared_ptr)std::atomic_load(std::shared_ptr)std::atomic_load_explicit(std::shared_ptr)std::atomic_store(std::shared_ptr)std::atomic_store_explicit(std::shared_ptr)std::atomic_exchange(std::shared_ptr)std::atomic_exchange_explicit(std::shared_ptr)std::atomic_compare_exchange_weak(std::shared_ptr)std::atomic_compare_exchange_strong(std::shared_ptr)std::atomic_compare_exchange_weak_explicit(std::shared_ptr)std::atomic_compare_exchange_strong_explicit(std::shared_ptr)specializes atomic operations for std::shared_ptr (function template)

帮助者类

std::hash (C++11)hash support for std::shared_ptr (class template specialization)

注记

对象的所有权只能与另一个对象共享。shared_ptr通过复制构造或复制将其值分配给另一个shared_ptr.建造一个新的shared_ptr使用另一个用户拥有的原始基础指针shared_ptr导致行为不明。

std::shared_ptr可以与不完全类型T但是,来自原始指针%28的构造函数template<class Y> shared_ptr(Y*)%29template<class Y> void reset(Y*)成员函数只能通过指向完整类型%28的指针调用,std::unique_ptr可以从指向不完整类型%29的原始指针构造。

执行说明

在一个典型的实现中,std::shared_ptr只包含两个指针:

  • 返回的存储指针%281get()29%;

  • 指向控制块...

控制块是一个动态分配的对象,它保存:

  • 指向托管对象或托管对象本身的指针;

  • 删除%28类型-删除%29;

  • 分配器%28类型-擦除%29;

  • 的数目shared_ptrs拥有托管对象;

  • 的数目weak_ptrs引用托管对象。

何时shared_ptr是通过调用std::make_sharedstd::allocate_shared,控制块和托管对象的内存都是用单个分配创建的。托管对象是在控制块的数据成员中就地构造的.。何时shared_ptr是通过shared_ptr构造函数、托管对象和控制块必须分开分配。在这种情况下,控制块存储指向托管对象的指针。

对象持有的指针。shared_ptr直接返回的是get(),而控制块持有的指针/对象是当共享所有者数达到零时将被删除的指针/对象。这些指针不一定相等。

破坏者shared_ptr减少控制块的共享所有者的数量。如果计数器达到零,则控制块调用托管对象的析构函数。控件块直到std::weak_ptr计数器也达到零。

在实际实现中,弱指针的数量可能增加如果有指向同一控制块的共享指针。

为了满足线程安全要求,引用计数器通常使用等效的std::atomic::fetch_add带着std::memory_order_relaxed%28递减需要更强的排序才能安全地销毁控制块%29。

二次

#include <iostream> #include <memory> #include <thread> #include <chrono> #include <mutex> struct Base { Base() { std::cout << " Base::Base()\n"; } // Note: non-virtual destructor is OK here ~Base() { std::cout << " Base::~Base()\n"; } }; struct Derived: public Base { Derived() { std::cout << " Derived::Derived()\n"; } ~Derived() { std::cout << " Derived::~Derived()\n"; } }; void thr(std::shared_ptr<Base> p) { std::this_thread::sleep_for(std::chrono::seconds(1) std::shared_ptr<Base> lp = p; // thread-safe, even though the // shared use_count is incremented { static std::mutex io_mutex; std::lock_guard<std::mutex> lk(io_mutex std::cout << "local pointer in a thread:\n" << " lp.get() = " << lp.get() << ", lp.use_count() = " << lp.use_count() << '\n'; } } int main() { std::shared_ptr<Base> p = std::make_shared<Derived>( std::cout << "Created a shared Derived (as a pointer to Base)\n" << " p.get() = " << p.get() << ", p.use_count() = " << p.use_count() << '\n'; std::thread t1(thr, p), t2(thr, p), t3(thr, p p.reset( // release ownership from main std::cout << "Shared ownership between 3 threads and released\n" << "ownership from main:\n" << " p.get() = " << p.get() << ", p.use_count() = " << p.use_count() << '\n'; t1.join( t2.join( t3.join( std::cout << "All threads completed, the last one deleted Derived\n"; }

二次

可能的产出:

二次

Base::Base() Derived::Derived() Created a shared Derived (as a pointer to Base) p.get() = 0xc99028, p.use_count() = 1 Shared ownership between 3 threads and released ownership from main: p.get() = (nil), p.use_count() = 0 local pointer in a thread: lp.get() = 0xc99028, lp.use_count() = 3 local pointer in a thread: lp.get() = 0xc99028, lp.use_count() = 4 local pointer in a thread: lp.get() = 0xc99028, lp.use_count() = 2 Derived::~Derived() Base::~Base() All threads completed, the last one deleted Derived

二次

© cppreference.com

在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。

http://en.cppreference.com/w/cpp/Memory/Shared[医]PTR