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 type | Definition |
---|---|
element_type | T (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_shared | creates a shared pointer that manages a new object (function template) |
---|---|
allocate_shared | creates 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_deleter | returns 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 | 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
只包含两个指针:
- 返回的存储指针%281
get()
29%;
- 指向
控制块
...
控制块是一个动态分配的对象,它保存:
- 指向托管对象或托管对象本身的指针;
- 删除%28类型-删除%29;
- 分配器%28类型-擦除%29;
- 的数目
shared_ptr
s拥有托管对象;
- 的数目
weak_ptr
s引用托管对象。
何时shared_ptr
是通过调用std::make_shared
或std::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。