栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++智能指针之shared

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++智能指针之shared

文章目录
  • C++智能指针之shared_ptr
    • shared_ptr篇
      • 简介
      • 成员函数
        • 构造函数
          • 默认构造
          • 空指针构造
          • 指针构造
          • 指针构造 + 删除器
          • 指针构造 + 删除器 + 内存分配器
          • 拷贝构造
          • 移动构造
          • 从其它类型的管理指针移动构造
          • 别名构造函数
        • 析构函数
        • get
        • operator*
        • operator->
        • use_count
        • unique
        • operator bool
        • owner_before
        • operator
        • swap
        • reset

C++智能指针之shared_ptr shared_ptr篇 简介

shared_ptr是一种定义在中的智能指针,用于管理指针的存储,提供智能资源回收,并且与内置指针相比几乎没有开销(取决于使用的删除器)。与unique_ptr 区别就是该指针可以和其它对象共享,shared_ptr 类型的对象具有获得指针所有权并共享该所有权的能力:一旦获得所有权,指针的所有者组将在他们中的最后一个释放该所有权时负责删除该指针(内部实现采用引用计数的方式),当然也可以通过shared_ptr::reset主动释放。

如果俩个对象都是通过指针构造来的,那么他们是俩个对象指针,不会共享对象。

成员函数 构造函数 默认构造
constexpr shared_ptr() noexcept;
{
    std::cout << "nn";
    std::shared_ptr p1;
    std::cout << "p1 use count:" << p1.use_count() << 'n';
    
}
空指针构造
constexpr shared_ptr(nullptr_t) : shared_ptr() {}
{
    std::cout << "nn";
    std::shared_ptr p2(nullptr);
    std::cout << "p2 use count:" << p2.use_count() << 'n';
    
}
指针构造

获取对象的所有权,并将use_count置为1。

template  explicit shared_ptr (U* p);
{
    std::cout << "nn";
    std::shared_ptr p3(new TestPtr("p3"));
    std::cout << "p3 use count:" << p3.use_count() << 'n';
    
}
指针构造 + 删除器
template  shared_ptr (U* p, D del);
template  shared_ptr (nullptr_t p, D del);
{
std::cout << "nn";
std::shared_ptr p4(new TestPtr("p4"), std::default_delete());
std::cout << "p4 use count:" << p4.use_count() << 'n';

}
指针构造 + 删除器 + 内存分配器
template  shared_ptr (U* p, D del, Alloc alloc);
template  shared_ptr (nullptr_t p, D del, Alloc alloc);
{
    std::cout << "nn";
    std::shared_ptr p5(new TestPtr("p5"), std::default_delete(), std::allocator());
    std::cout << "p5 use count:" << p5.use_count() << 'n';
    
}
拷贝构造

若p不会空,则use_count加1;若p为空,则构造一个空对象。

shared_ptr (const shared_ptr& x) noexcept;
template  shared_ptr (const shared_ptr& x) noexcept;
{
    std::cout << "nn";
    std::shared_ptr p(new TestPtr("p"));
    std::shared_ptr p6(p);
    std::cout << "p6 use count:" << p6.use_count() << 'n';
    
}
移动构造

获取P对象的所有权,并且P成为空对象。

shared_ptr (shared_ptr&& x) noexcept;
template  shared_ptr (shared_ptr&& x) noexcept;
{
std::cout << "nn";
std::shared_ptr p(new TestPtr("p"));
std::cout << "p  use count:" << p.use_count() << " -> " << p.get() << "n";
std::shared_ptr p7(std::move(p));
std::cout << "p7 use count:" << p7.use_count() << " -> " << p7.get() << "n";
std::cout << "p  use count:" << p.use_count() << " -> " << p.get() << "n";

}
从其它类型的管理指针移动构造

获取p对象的所有权,并将use_count置为1,对象P释放所有权。

template  shared_ptr (auto_ptr&& x);
template  shared_ptr (unique_ptr&& x);
{
    std::cout << "nn";
    std::unique_ptr p(new TestPtr("unique_ptr"));
    std::cout << " p-> " << p.get() << "n";
    std::shared_ptr p8(std::move(p));
    std::cout << "p8 use count:" << p8.use_count() << " -> " << p8.get() << "n";
    std::cout << " p-> " << p.get() << "n";
    
}
别名构造函数

该对象不拥有 p,并且不会管理其存储。 相反,它共同拥有 x 的托管对象并算作 x 的一种附加用途。 它还将在释放时删除 x 的指针(而不是 p)它可以用来指向已经被管理的对象的成员。

template  shared_ptr (const shared_ptr& x, element_type* p) noexcept;
{
    std::cout << "nn";
    struct Data
    {
    
    int *total;
    };

    std::shared_ptr p = std::make_shared();
    p->total = new int;
    *p->total = 10;
    std::cout << "p  use count:" << p.use_count() << " -> " << p.get() << "n";
    std::cout << "p->total:" << p->total << " -> " << *p->total << "n";
    std::shared_ptr p9(p, p->total);
    std::cout << "p9 use count:" << p9.use_count() << " -> " << p9.get() << "n";
    std::cout << "p  use count:" << p.use_count() << " -> " << p.get() << "n";
    std::cout << "p->total:" << p->total << " -> " << *p->total << "n";
    delete p->total;
    
}
析构函数

销毁shared_ptr对象:

  • 如果 use_count 大于 1(即对象与其他 shared_ptr 对象共享其托管对象的所有权):与其共享所有权的其他对象的使用计数减 1。
  • 如果 use_count 为 1(即对象是托管指针的唯一所有者):删除其拥有的指针指向的对象(如果 shared_ptr 对象是用特定的删除器构造的,则调用 this;否则,函数使用运算符 删除)。
  • 如果 use_count 为零(即对象为空),则此析构函数没有副作用。
{
    {
        std::shared_ptr p0;
        {
            {
                std::cout << "nn";
                auto deleter = [](int *p)
                {
                    delete p;
                    std::cout << "[deleter called] donen";
                };

                std::shared_ptr p(new int, deleter);
                p0 = p;
                std::cout << "p  use count:" << p.use_count() << " -> " << p.get() << "n";
                std::cout << "p0 use count:" << p0.use_count() << " -> " << p0.get() << "n";
            }
            // 在此 use_count 减为1,不析构
            std::cout << "[OK] after leave pn";
            std::cout << "p0  use count:" << p0.use_count() << " -> " << p0.get() << "n";
        }
	}
    //在此 use_count 减为0,析构p
}

get

返回对象所存储指针的地址。

element_type* get() const noexcept;
operator*

返回对象存储指针的解引用。

element_type& operator*() const noexcept;
operator->

解引用对象管理指针的成员。

element_type* operator->() const noexcept;
use_count

返回在与此对象(包括它)相同的指针上共享所有权的 shared_ptr 对象的数量。

long int use_count() const noexcept;
unique

返回 shared_ptr 对象是否不与其他 shared_ptr 对象共享其指针的所有权(即,它是唯一的)。

bool unique() const noexcept;
{
    std::shared_ptr p1(nullptr);
    std::shared_ptr p2 = std::make_shared("p2");
    std::shared_ptr p3 = std::make_shared("p3");

    p1 = p2;
    std::cout << "p1 unqiue :" << (p1.unique() ? " true" : " false") << "n"; // false
    std::cout << "p2 unqiue :" << (p2.unique() ? " true" : " false") << "n"; // false
    std::cout << "p3 unqiue :" << (p3.unique() ? " true" : " false") << "n"; // true
}

operator bool

检查对象存储的指针是否为空;

explicit operator bool() const noexcept;
{
    std::shared_ptr p1(nullptr);
    std::shared_ptr p2 = std::make_shared("p2");

    std::cout << "p1 bool :" << (!p1 ? " true" : " false") << "n"; // false
    std::cout << "p2 bool :" << (!p2 ? " true" : " false") << "n"; // true
}

owner_before

根据严格的所有者的弱顺序,返回对象是否被认为在 x 之前。

template  bool owner_before (const shared_ptr& x) const;
template  bool owner_before (const weak_ptr& x) const;
{
    int* p = new int(10);
    std::shared_ptr a(new int(20));
    std::shared_ptr b(a, p);  // 别名构造
    std::shared_ptr c = a;

    std::cout << "*a:" << *a << 'n';
    std::cout << "*b:" << *b << 'n';
    std::cout << "comparing a and b...n" << std::boolalpha;
    std::cout << "value-based: " << (!(a < b) && !(b < a)) << 'n';
    std::cout << "owner-based: " << (!a.owner_before(b) && !b.owner_before(a)) << 'n';
    std::cout << "c is before a: " << (c.owner_before(a)) << 'n';
    std::cout << "a is before : " << (a.owner_before(c)) << 'n';
    std::cout << "b is before a: " << (b.owner_before(a)) << 'n';

    delete p;
}

operator
  • 复制(1) 将该对象添加为 x 资产的共享所有者,从而增加它们的 use_count。
shared_ptr& operator= (const shared_ptr& x) noexcept;
template  shared_ptr& operator= (const shared_ptr& x) noexcept;
  • 移动 (2) 将所有权从 x 转移到 shared_ptr 对象,而不改变 use_count。 x 变成一个空的 shared_ptr (就像默认构造的一样)。
shared_ptr& operator= (shared_ptr&& x) noexcept;
template  shared_ptr& operator= (shared_ptr&& x) noexcept;
  • 来自其他托管指针类型 (3) 的移动分配也转移所有权,并使用设置为使用计数 1 进行初始化。
template  shared_ptr& operator= (auto_ptr&& x);
template  shared_ptr& operator= (unique_ptr&& x);
  • 此外,在上述所有情况下,调用此函数的副作用与在其值更改之前调用 shared_ptr 的析构函数具有相同的副作用(如果此 shared_ptr 是唯一的,则包括删除托管对象)。
  • 不能将指针的值直接分配给 shared_ptr 对象。 可以使用 make_shared 或 member reset 代替。
{
    std::shared_ptr p1(nullptr);
    std::shared_ptr p2 = make_shared("p2");
    std::shared_ptr p3 = make_shared("p3");

    std::cout << "A:n";
    std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n';
    std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n';
    std::cout << "p3 use count:" << p3.use_count() << ' ' << p3.get() << 'n';

    
    p1 = p2;
    std::cout << "copy:n";
    std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n';
    std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n';
    std::cout << "p3 use count:" << p3.use_count() << ' ' << p3.get() << 'n';

    
    p1 = std::move(p3);
    std::cout << "move:n";
    std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n';
    std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n';
    std::cout << "p3 use count:" << p3.use_count() << ' ' << p3.get() << 'n';
}

swap

交换对象所有权,将 shared_ptr 对象的内容与 x 的内容交换,在它们之间转移任何托管对象的所有权,而不会破坏或更改其中任何一个的使用计数。

void swap (shared_ptr& x) noexcept;
{
    std::shared_ptr p1 = make_shared("p1");
    std::shared_ptr p2 = make_shared("p2");
    std::shared_ptr p3(nullptr);
 
    std::cout << "init:n";
    std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n'; // 1
    std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n'; // 1
    std::cout << "p3 use count:" << p3.use_count() << ' ' << p3.get() << 'n'; // 0
 
    p1.swap(p2);
    std::cout << "swap p2 -> p1:n";
    std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n'; // 1
    std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n'; // 1
    std::cout << "p3 use count:" << p3.use_count() << ' ' << p3.get() << 'n'; // 0

    p3.swap(p1);
    std::cout << "swap p1 -> p3:n";
    std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n'; // 0
    std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n'; // 1
    std::cout << "p3 use count:" << p3.use_count() << ' ' << p3.get() << 'n'; // 1
}

reset
(1)	void reset() noexcept;
(2)	template  void reset (U* p);
(3)	template  void reset (U* p, D del);
(4)	template  void reset (U* p, D del, Alloc alloc);
  • 对于 reset (1),对象变为空(就像默认构造的一样),释放所有权。
  • 在其他情况下,shared_ptr 获得 p 的所有权,使用计数为 1,并且 - 可选 - 分别使用 del 和/或 alloc 作为删除器和分配器。
  • 调用此函数具有与 shared_ptr 的析构函数在其值更改之前调用相同的副作用(包括如果此 shared_ptr 是唯一的则删除托管对象)。
{
    std::shared_ptr p1(nullptr);
    std::shared_ptr p2 = make_shared("p2");
 
    std::cout << "init:n";
    std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n'; // 0
    std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n'; // 1

    p1.reset(new TestPtr("new p1"));
    p2.reset();

    std::cout << "reset:n";
    std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n'; // 1
    std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n'; // 0
    

}
转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号