c++11 智能指针浅析

之前学习c++没有接触到c++11的一些新的特性,最近啊研究boost库的时候有接触到新的东西出来,所以看了一下智能指针的内容。

c++智能指针的优势:

相对于我们传统的指针在new之后堆区的空间不知该什么时候delete掉,所以c++11推出了智能指针。更加方便对指针所指向的资源进行保护和合理的释放。实现超出区域之后就会自动释放的功能。

shared_ptr , auto_ptr, weak_ptr还有unique_ptr是我们常用的几个模板类。

c++智能指针实现的原理:

利用模板和重载的特性,在模板类里面实现定义好可能会需要的各种模板函数,这些函数是重载的关系。

auto智能指针内部大致包含

  • 一个空指针,用来接收构造时传进来的指针
  • 很多个不同参数个数的模板
  • 一些用来进行操作的内部函数

注意我们访问auto_ptr的成员函数时用的是“.”,访问指向对象的成员时用的是“->”。我们也可用声明一个空智能指针,这很好理解,虽然它叫做智能指针但是它是一个模板类,这个的作用就是用来管理你所传进来的指针,这个对象的指针调用内部函数的时候用指针的'->'而对于自己内部函数,作为一个类就直接使用'.'。

class Test
{
public:
    Test(string s)
    {
        str = s;
        cout<<"Test creat\n";
    }
    ~Test()
    {
        cout<<"Test delete:"<<str<<endl;
    }
    string& getStr()
    {
        return str;
    }
    void setStr(string s)
    {
        str = s;
    }
    void print()
    {
        cout<<str<<endl;
    }
private:
    string str;
};
 
 
int main()
{
    //构造的时候可以直接在里面new一个指针出来
    auto_ptr<Test> ptest(new Test("123"));
    ptest->setStr("hello ");
    ptest->print();
    ptest.get()->print();
    ptest->getStr() += "world !";
    (*ptest).print();
    ptest.reset(new Test("123")); 
    //当一个指针里面的内容被reset之后,它原来所指向的内容如果count减为0就会被释放。
    //所以在这里就会调用一个析构函数
    ptest->print();
    return 0;
    //在离开这个作用域的时候,ptest的数为1会释放空间,进而调用析构函数
}

据说现在auto_ptr都被舍弃了,因为不能用于容器,而且一旦重新赋值就会导致原来的空间被释放,所以就会有很多指针变为NULL,所以STL不能用。

还有一种比较好用的指针就是shared_ptr这个模板类

shared_ptr的内部除了保存指针的部分,剩下还有一部分的功能就是计数,统计到底有地方享有这个指针的所有权。

扫描二维码关注公众号,回复: 4726379 查看本文章

shared_ptr类型的对象具有获取指针的所有权并且共享所有权的能力,一旦他们拥有了所有权,当他们中的最后一个释放所有权的时候,一个指针的所有者会负责对他的删除负责。可以通过成员函数use_count()来查看资源的所有者个数。出了可以通过new来构造,还可以通过传入auto_ptr, unique_ptr,weak_ptr来构造。当我们调用release()时,当前指针会释放资源所有权,计数减一。当计数等于0时,资源会被释放。

也就是说如果该指针所指向的资源还有所有者就不会被释放空间,但是也会造成一些麻烦,比如说当两个指针互相应用对方的时候两个指针格子的资源都会加一,也就是两个都是2,那么就会在俩开作用域的时候出现不能析构的死锁现象。

class A
{
public:
    shared_ptr<B> pb_;
};
class B
{
public:
    shared_ptr<A> pa_;
};
 
void testfun()
{
    shared_ptr<B> pb(new B());
    shared_ptr<A> pa(new A());
    pb->pa_ = pa;
    pa->pb_ = pb;
    cout<<pb.use_count()<<endl;
    cout<<pa.use_count()<<endl;
}
 
int main()
{
    fun();
    return 0;
}

出现这种情况的话,我们可以配合weak_ptr来解决,就这个模板类的名字我们可以知道,它是一个比较'弱'的指针,这个弱体现在它是对对象的一种弱引用,不会增加对象的引用计数。和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得shared_ptr。

使用shared_ptr的几个注意点

  1. 虽然它是一种很好的方法去优化内存管理,但是不可避免的会占用资源
  2. 最好不要让多个共享指针指向一块内存空间,因为在释放的时候会多次释放。
  3. 注意无论是最初的free也好,delete也好都不能对除了堆区的内存空间操作,栈区一操作就容易崩。赋初值的也要堆区的指针。
  4. 不能将纯指针直接赋给智能指针,因为智能指针不是指针是对指针操作和保护的类,是模板类.

参考资料

https://blog.csdn.net/man_sion/article/details/77196766  

http://www.cnblogs.com/TenosDoIt/p/3456704.html

猜你喜欢

转载自blog.csdn.net/weixin_42427338/article/details/83039043