c++11 智能指针 (std::shared_ptr)(三)

本文详细解读了C++11中的shared_ptr类,包括它的定义、get方法、解引用操作、引用计数、管理对象检查以及提供基于拥有者的排序。通过示例展示了如何使用shared_ptr进行智能指针的内存共享与所有权管理。
摘要由CSDN通过智能技术生成
  定义于头文件 <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) 是未指定的。

T 是数组类型时,是否声明这两个函数是未指定的。

(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';

}

输出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值