定义于头文件 <memory>
template< class T > class shared_ptr; (C++11 起)
返回存储的指针
std::shared_ptr<T>::get
T* get() const noexcept; (C++17 前)
element_type* get() const noexcept; (C++17 起)
返回存储的指针。
参数
(无)
返回值
存储的指针。
注意
shared_ptr
可能在存储指向一个对象的指针时共享另一对象的所有权。 get()
返回存储的指针,而非被管理指针。
调用示例
#include <iostream>
#include <memory>
#include <string>
void output(std::string msg, int const* pInt)
{
std::cout << msg << *pInt << "\n";
}
int main()
{
int* pInt = new int(42);
std::shared_ptr<int> pShared = std::make_shared<int>(42);
output("Naked pointer ", pInt);
// output("Shared pointer ", pShared); // 编译错误
output("Shared pointer with get() ", pShared.get());
delete pInt;
}
输出
解引用存储的指针
std::shared_ptr<T>::operator*,
std::shared_ptr<T>::operator->
T& operator*() const noexcept; (1)
T* operator->() const noexcept; (2)
解引用所存储的指针。若存储的指针为空,则行为未定义。
参数
(无)
返回值
1) 解引用存储的指针所得的结果,即 *get()
2) 存储的指针,即 get()
注意
T
是(可有 cv 限定的) void 类型时,是否声明函数 (1) 是未指定的。
| (C++17 起) |
以上情况下,若声明函数,则其返回类型是未指定的,但保证函数声明合法,函数定义未必合法。这使得 std::shared_ptr<void> 可以实例化。
调用示例
#include <iostream>
#include <memory>
struct Foo
{
Foo(int in) : a(in) {}
void print() const
{
std::cout << "a = " << a << '\n';
}
int a;
};
int main()
{
auto ptr = std::make_shared<Foo>(10);
ptr->print();
(*ptr).print();
}
返回 shared_ptr 所指对象的引用计数
std::shared_ptr<T>::use_count
long use_count() const noexcept;
返回管理当前对象的不同 shared_ptr
实例(包含 this )数量。若无管理对象,则返回 0 。
多线程环境下, use_count 返回的值是近似的(典型实现使用 memory_order_relaxed 加载)
参数
(无)
返回值
管理当前对象的 shared_ptr
实例数量,或若无被管理对象则为 0 。
注意
常用使用包括
- 与 0 比较。若
use_count
返回零,则智能指针为空且不管理对象(无论被存储指针是否为空)。多线程环境下,这不隐含被管理对象的析构函数已完成。 - 与 1 比较。若
use_count
返回 1 ,则无其他拥有者。(被弃用成员函数 unique() 为此使用情况提供。)多线程环境中,这不隐含对象可以安全修改,因为先前拥有者对被管理对象的访问可能未完成,而因为新的共享拥有者可以同时引入,例如用 std::weak_ptr::lock 。
调用示例
#include <memory>
#include <iostream>
void fun(std::shared_ptr<int> sp)
{
std::cout << "fun: sp.use_count() == " << sp.use_count() << '\n';
}
int main()
{
auto sp1 = std::make_shared<int>(5);
std::cout << "sp1.use_count() == " << sp1.use_count() << '\n';
fun(sp1);
}
输出
检查是否有关联的管理对象
std::shared_ptr<T>::operator bool
explicit operator bool() const noexcept;
检查 *this 是否存储非空指针,即是否有 get() != nullptr 。
参数
(无)
返回值
若 true 存储非空指针则为 *this ,否则为 false 。
注意
空 shared_ptr (其中 use_count() == 0 )可能存储能以 get()
访问的非空指针,例如若它以别名使用构造函数创建。
调用示例
#include <iostream>
#include <memory>
void report(std::shared_ptr<int> ptr)
{
if (ptr) {
std::cout << "*ptr=" << *ptr << "\n";
} else {
std::cout << "ptr is not a valid pointer.\n";
}
}
int main()
{
std::shared_ptr<int> ptr;
report(ptr);
ptr = std::make_shared<int>(7);
report(ptr);
}
输出
提供基于拥有者的共享指针排序
std::shared_ptr<T>::owner_before
template< class Y >
bool owner_before( const shared_ptr<Y>& other) const noexcept;
template< class Y >
bool owner_before( const std::weak_ptr<Y>& other) const noexcept;
以实现定义的基于拥有者(与基于值相反)顺序,检查此 shared_ptr
是否先于 other
。二个智能指针仅若都占有同一对象或均为空才比较相等,即使由 get() 获得的指针不同(例如因为它们指向同一对象中的不同子对象)。
此顺序用于令共享和弱指针可用作关联容器中的关键,通常经由 std::owner_less 。
参数
other | - | 要比较的 std::shared_ptr 或 std::weak_ptr |
返回值
若 *this 前于 other
则为 true ,否则为 false 。常见实现比较控制块的地址。
调用示例
#include <iostream>
#include <memory>
struct Foo
{
int n1;
int n2;
Foo(int a, int b) : n1(a), n2(b) {}
};
int main()
{
auto p1 = std::make_shared<Foo>(1, 2);
std::shared_ptr<int> p2(p1, &p1->n1);
std::shared_ptr<int> p3(p1, &p1->n2);
std::cout << std::boolalpha
<< "p2 < p3 " << (p2 < p3) << '\n'
<< "p3 < p2 " << (p3 < p2) << '\n'
<< "p2.owner_before(p3) " << p2.owner_before(p3) << '\n'
<< "p3.owner_before(p2) " << p3.owner_before(p2) << '\n';
std::weak_ptr<int> w2(p2);
std::weak_ptr<int> w3(p3);
std::cout
// << "w2 < w3 " << (w2 < w3) << '\n' // won't compile
// << "w3 < w2 " << (w3 < w2) << '\n' // won't compile
<< "w2.owner_before(w3) " << w2.owner_before(w3) << '\n'
<< "w3.owner_before(w2) " << w3.owner_before(w2) << '\n';
}