auto_ptr, unique_ptr, shared_ptr and weak_ptr智能指针讲解

原创 2017年06月05日 11:23:29

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

CSDN视频网址:http://edu.csdn.net/lecturer/144

C ++库提供以下类型的智能指针的实现:

  • auto_ptr
  • unique_ptr
  • shared_ptr
  • weak_ptr

    它们都在内存头文件中声明。

auto_ptr

从C ++ 11开始,此类模板已被弃用。 unique_ptr是具有相似功能但具有改进的安全性的新工具。
auto_ptr是一个智能指针,用于管理通过新表达式获取的对象,并在auto_ptr本身被销毁时删除该对象。
当使用auto_ptr类描述一个对象时,它存储一个指向单个分配对象的指针,该对象可以确保当它超出范围时,它指向的对象必须被自动销毁。 它基于独占所有权模式,即同一类型的两个指针不能同时指向相同的资源。 如下面的程序所示,复制或分配指针会更改所有权,即源指针必须赋予目标指针所有权。

#include<iostream>
#include<memory>
using namespace std;
 
class A
{
public:
    void show() {  cout << "A::show()" << endl; }
};
 
int main()
{
    // p1 is an auto_ptr of type A
    auto_ptr<A> p1(new A);
    p1 -> show();
 
    // returns the memory address of p1
    cout << p1.get() << endl;
 
    // copy constructor called, this makes p1 empty.
    auto_ptr <A> p2(p1);
    p2 -> show();
 
    // p1 is empty now
    cout << p1.get() << endl;
 
    // p1 gets copied in p2
    cout<< p2.get() << endl;
 
    return 0;
}

Output:

A::show()
0x1b42c20
A::show()
0          
0x1b42c20
auto_ptr的拷贝构造函数和赋值运算符实际上并没有复制存储的指针,而是将它们传输出去,使第一个auto_ptr对象变为空。 这是实现严格所有权的一种方法,因此只有一个auto_ptr对象可以在任何给定时间拥有该指针,即在需要复制语义的情况下不应使用auto_ptr。

unique_ptr

std :: unique_ptr是在C ++ 11中开发的,用于替代std :: auto_ptr。unique_ptr是具有类似功能的新工具,但具有改进的安全性(无假拷贝分配),添加功能(删除器)和数组支持。 它是一个原始指针的容器。 它明确地防止复制其包含的指针,正如正常赋值那样会发生,即它只允许底层指针的一个所有者。
所以,当使用unique_ptr时,在任何一个资源上最多只能有一个unique_ptr,当该unique_ptr被破坏时,该资源将被自动声明。 另外,由于任何资源只能有一个unique_ptr,所以任何创建unique_ptr副本的尝试将导致编译时错误。

 unique_ptr<A> ptr1 (new A);

 // Error: can't copy unique_ptr
 unique_ptr<A> ptr2 = ptr1;
但是,unique_ptr可以使用新的语义,即使用std :: move()函数将包含的指针的所有权转移到另一个unique_ptr。

// Works, resource now stored in ptr2
unique_ptr<A> ptr2 = move(ptr1); 
所以,最好使用unique_ptr,当我们想要一个指向一个对象的指针,当该单个指针被销毁时将被回收。
// C++ program to illustrate the use of unique_ptr
#include<iostream>
#include<memory>
using namespace std;
 
class A
{
public:
    void show()
    {
        cout<<"A::show()"<<endl;
    }
};
 
int main()
{
    unique_ptr<A> p1 (new A);
    p1 -> show();
 
    // returns the memory address of p1
    cout << p1.get() << endl;
 
    // transfers ownership to p2
    unique_ptr<A> p2 = move(p1);
    p2 -> show();
    cout << p1.get() << endl;
    cout << p2.get() << endl;
 
    // transfers ownership to p3
    unique_ptr<A> p3 = move (p2);
    p3->show();
    cout << p1.get() << endl;
    cout << p2.get() << endl;
    cout << p3.get() << endl;
 
    return 0;
}

Output:

A::show()
0x1c4ac20
A::show()
0          // NULL
0x1c4ac20
A::show()
0          // NULL
0          // NULL
0x1c4ac20

下面的代码返回一个资源,如果我们没有显式捕获返回值,资源将被清除。 如果我们这样做,那么我们拥有该资源的独占所有权, 这样我们可以将unique_ptr看作更安全,更好的替换auto_ptr。

unique_ptr<A> fun()
{
    unique_ptr<A> ptr(new A);

    /* ...
       ... */

    return ptr;
}
何时使用unique_ptr?
当您想拥有资源的唯一所有权(Exclusive)时,请使用unique_ptr, 只有一个unique_ptr可以指向一个资源 因为单个资源可以有一个unique_ptr,所以不可能将一个unique_ptr复制到另一个。

shared_ptr

shared_ptr是原始指针的容器。 它是一个引用计数模型,即它与shared_ptr的所有副本合作维护其包含的指针的引用计数。 因此,每当一个新的指针指向资源时,计数器就会递增,当调用对象的析构函数时递减计数器。

引用计数:这是一种将资源数量,指针或句柄存入资源(如对象,内存块,磁盘空间或其他资源)的技术。

引用计数大于0,直到所有的shared_ptr副本都被删除,所包含的原始指针引用的对象将不会被销毁。因此,当我们要为一个原始指针分配给多个所有者时,我们应该使用shared_ptr。
#include<iostream>
#include<memory>
using namespace std;
 
class A
{
public:
    void show()
    {
        cout<<"A::show()"<<endl;
    }
};
 
int main()
{
    shared_ptr<A> p1 (new A);
    cout << p1.get() << endl;
    p1->show();
    shared_ptr<A> p2 (p1);
    p2->show();
    cout << p1.get() << endl;
    cout << p2.get() << endl;
 
    // Returns the number of shared_ptr objects
    //referring to the same managed object.
    cout << p1.use_count() << endl;
    cout << p2.use_count() << endl;
 
    // Relinquishes ownership of p1 on the object
    //and pointer becomes NULL
    p1.reset();
    cout << p1.get() << endl;
    cout << p2.use_count() << endl;
    cout << p2.get() << endl;
 
    return 0;
}

Output:

0x1c41c20
A::show()
A::show()
0x1c41c20
0x1c41c20
2
2
0          // NULL
1
0x1c41c20

何时使用shared_ptr?

如果要共享资源的所有权,请使用shared_ptr。 很多shared_ptr可以指向单个资源。 shared_ptr维护这个引用计数,当所有shared_ptr指向资源超出范围时,资源被破坏。

weak_ptr

将weak_ptr创建为shared_ptr的副本。 它提供对一个或多个shared_ptr实例拥有的对象的访问权限,但不参与引用计数。 weak_ptr的存在或破坏对shared_ptr或其他副本没有影响。 在某些情况下需要中断shared_ptr实例之间的循环引用。

循环依赖(shared_ptr的问题):让我们考虑一个场景,我们有两个类A和B,它们都有指向其他类的指针。 所以,它总是像A指向B和B指向A.因此,use_count永远不会达到零,并且永远不会被删除。
这是我们使用弱指针(weak_ptr)的原因,因为它们不是引用计数。 所以,weak_ptr被声明的类没有很强的保持,即所有权不被共享,但是他们可以访问这些对象。

所以,在shared_ptr的情况下,由于循环依赖关系use_count从不达到零,这是阻止使用weak_ptr的,通过将A_ptr声明为weak_ptr来消除这个问题,因此A类不拥有它,只能访问它,我们还需要检查 对象的有效性可能超出范围。 一般来说,这是一个设计问题。

什么时候使用weak_ptr?

当你想要从多个地方引用你的对象 - 对于那些可以忽略和释放它们的引用(所以当你尝试取消引用时,它们只会注意到对象已经不见了)。

本篇博客主要是给读者对智能指针的使用做一个总结。。。。。。。。






版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jxw167/article/details/72864554

精通C语言指针

指针被誉为C语言的精髓、C本质上是加了一层语法糖的汇编,引进当时先进的函数,保留了汇编强大的地址直接访问功能 —— 指针,使其高效灵活。本课程是黄强老师对于指针的一次专题讲解,相信能给大家带来收获!
  • 2017年09月06日 19:22

浅谈智能指针auto_ptr/shared_ptr/unique_ptr

一.智能指针1.引入我们通常使用类似new申请一块空间,交由一个指针指向,假如说最后忘记delete,将会造成内存泄露。而智能指针的出现,就是对这种问题的解决方式,智能指针类似指针,却可以用于管理动态...
  • derkampf
  • derkampf
  • 2017-05-23 19:24:08
  • 1410

stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结

在一次面试过程中被问到了stl中的四种智能指针的用法 由于经验不足,我只知道auto_ptr和shared_ptr,然后还说了一个弱...    然后面试官就提示是weak_ptr,之后他又主动说出...
  • zsc_976529378
  • zsc_976529378
  • 2016-08-19 14:25:03
  • 2445

auto_ptr与shared_ptr --- auto_ptr (1)

Roger (roger2yi@gmail.com) 这篇文章试图说明如何使用auto_ptr和shared_ptr,从而使得动态分配对象的使用和管理更安全,方便。除了一般的使用说明外,更主要是说明它...
  • rogeryi
  • rogeryi
  • 2006-12-14 13:54:00
  • 5089

c++智能指针:auto_ptr shared_ptr

1. 简介 C++程序员最痛苦的莫过于对内存的管理,由于没有像C# 和 java的内存回收机制,C++程序员在复杂的程序中容易造成内存的泄露。即使程序员十分小心,异常的产生也有可能会造成部分内存的泄...
  • gui694278452
  • gui694278452
  • 2015-06-03 18:44:10
  • 3029

auto_ptr与shared_ptr 的区别

在C++中,内存资源的管理经常是一个令人头痛的问题,指针的错误使用经常是造成内存泄露和“未定义行为”的根源。很多资源被动态分配与heap内而后被用于单一区块或函数内。它们应该在控制流离开那个区块或函数...
  • ExtraMan
  • ExtraMan
  • 2014-12-10 15:46:20
  • 561

auto_ptr 与 shared_ptr 用法和区别总结

1.auto_ptr 被复制后,将失去原来所致资源的所有权;
  • Manketon
  • Manketon
  • 2014-07-08 12:29:29
  • 2259

C++中的智能指针——auto_ptr, unique_ptr, shared_ptr和weak_ptr

http://www.cnblogs.com/lanxuezaipiao/p/4132096.html STL一共给我们提供了四种智能指针:auto_ptr、unique_ptr、shared_ptr...
  • yyf_it
  • yyf_it
  • 2016-08-24 22:52:30
  • 537

auto_ptr、shared_ptr、weak_ptr、scoped_ptr用法小结

auto_ptr   auto_ptr是现在标准库里面一个轻量级的智能指针的实现,存在于头文件 memory中,之所以说它是轻量级,是因为它只有一个成员变量(拥有对象的指针),相关的调用开销也...
  • lollipop_jin
  • lollipop_jin
  • 2013-01-14 09:05:10
  • 11627

shared_ptr

shared_ptr是一个最像指针的"智能指针",是boost.smart_ptr库中最有价值、最重要的组成部分,也是最有用的,Boost库的许多组件--甚至还包括其他一些领域的智能指针都使用了sha...
  • sndaxdrs
  • sndaxdrs
  • 2011-02-09 16:22:00
  • 72629
收藏助手
不良信息举报
您举报文章:auto_ptr, unique_ptr, shared_ptr and weak_ptr智能指针讲解
举报原因:
原因补充:

(最多只允许输入30个字)