C++ 智能指针

  • 💂 个人主页:风间琉璃
  • 🤟 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主
  • 💬 如果文章对你有帮助、欢迎关注点赞收藏(一键三连)和订阅专栏

目录

一、智能指针定义

二、四种智能指针

1.std::auto_ptr

2.std::unique_ptr

3.std::shared_ptr

4.std::weak_ptr


在这里插入图片描述

一、智能指针定义

智能指针:将指针对象模板化实现了类型的通用,构成智能指针。 

实现智能指针时需要考虑以下三个方面的问题:

在对象构造时获取资源在对象析构的时候释放资源,利用对象的生命周期来控制程序资源,即RAII特性。

②对*->运算符进行重载,使得该对象具有像指针一样的行为。

③智能指针对象的拷贝问题。

RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、互斥量等等)的简单技术。 

智能指针就是要模拟原生指针的行为,当将一个指针赋值给另一个指针时,目的就是让这两个指针指向同一块内存空间,所以这里本就应该进行浅拷贝,但单纯的浅拷贝又会导致空间被多次释放,因此根据解决智能指针拷贝问题方式的不同,从而衍生出了不同版本的智能指针

智能指针对象销毁时会自动释放记录的地址空间,很大程度上避免了内存泄漏的发生

二、四种智能指针

C++预定义了智能指针,可以直接使用,智能指针有4种,使用它们需要添加头文件memory。

智能指针的作用是管理一个指针,因为存在以下这种情况:申请的空间在函数结束时忘记释放,造成内存泄漏。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间。

操作的方法:在构造函数时,将类外需要管理的指针传进去,可以给个空的缺省值,然后重载“->”“*”“=”…等符号,然后在析构函数时,释放这个指针空间,形成对这个指针的智能的管理。
 

1.std::auto_ptr

auto_ptr是c++98版本库中提供的智能指针,该指针解决上诉的问题采取的措施是管理权转移的思想,也就是原对象拷贝给新对象的时候,原对象就会被设置为nullptr,此时只有新对象指向一块资源空间。 

auto_ptr是C++98中引入的智能指针,auto_ptr通过管理权转移的方式解决智能指针的拷贝问题保证一个资源在任何时刻都只有一个对象在对其进行管理,这时同一个资源就不会被多次释放了

如果auto_ptr调用拷贝构造函数或者赋值重载函数后,如果再去使用原来的对象的话,那么整个程序就会崩溃掉(因为原来的对象被设置为nullptr),这对程序是有很大的伤害的。所以C++17移除了用auto_ptr智能指针。


class Object{
public:
    Object(string s=""):str(s){}
    ~Object(){cout<<"~Object()"<<endl;}

    void show()const
    {
        cout<<this->str<<endl;
    }

    void set_str(const string &s)
    {
        this->str = s;
    }

private:
    string str;
};

int main()
{
    //管理 string *的指针
    auto_ptr<string> pa(new string("hello"));
    cout<<pa->c_str()<<endl;

    auto_ptr<string> pa1 = pa;//pa将被置空
    //cout<<pa->c_str()<<endl;传递导致失效
    cout<<pa1->c_str()<<endl;
   
    auto_ptr<Object> ao(new Object("hello"));
    auto_ptr<Object> ao1 = ao;//ao1被置空

    return 0;
}

2.std::unique_ptr

unique_ptr是C++11中引入的智能指针,unique_ptr通过防拷贝的方式解决智能指针的拷贝问题,它直接将拷贝构造函数和赋值重载函数给禁用掉也就是简单粗暴的防止对智能指针对象进行拷贝,这样也能保证资源不会被多次释放

unique_ptr对其持有的堆内存具有唯一拥有权,也就是不可以拷贝或者复制给其他对象,当unique_ptr对象销毁时会释放掉其持有的堆内存。

int main()
{
	std::unique_ptr<int> up1(new int(0));
	//std::unique_ptr<int> up2(up1); //error
	return 0;
}

3.std::shared_ptr

share_ptr是c++11版本库中的智能指针,shared_ptr允许多个智能指针可以指向同一块资源,并且能够保证共享的资源只会被释放一次,因此是程序不会崩溃掉。

 shared_ptr采用的是引用计数原理来实现多个shared_ptr对象之间共享资源:

①shared_ptr在内部会维护着一份引用计数,用来记录该份资源被几个对象共享。

②当一个shared_ptr对象被销毁时(调用析构函数),析构函数内就会将该计数减1。

③如果引用计数减为0后,则表示自己是最后一个使用该资源的shared_ptr对象,必须释放资源。

④如果引用计数不是0,就说明自己还有其他对象在使用,则不能释放该资源,否则其他对象就成为野指针。
 

引用计数是用来记录资源对象中有多少个指针指向该资源对象。 

 销毁过程:

class Object{
public:
    Object(string s=""):str(s){}
    ~Object(){cout<<"~Object()"<<endl;}

    void show()const
    {
        cout<<this->str<<endl;
    }

    void set_str(const string &s)
    {
        this->str = s;
    }

private:
    string str;
};

int main()
{

    shared_ptr<string> ss(new string("byebye"));
    cout<<ss->c_str()<<endl;

    shared_ptr<string> ss1 = ss;//共享
    ss1->append("冬天");
    cout<<ss->c_str()<<endl;
    cout<<ss1->c_str()<<endl;

    shared_ptr<Object> so(new Object("byebye"));
    shared_ptr<Object> so1;
    so1 = so;//共享
    so1->set_str("你好");
    so->show();
    so1->show();

    return 0;
}

4.std::weak_ptr

weak_ptr是C++11中引入的智能指针,weak_ptr不是用来管理资源的释放的,它主要是用来解决shared_ptr的循环引用问题的。

weak_ptr支持用shared_ptr对象来构造weak_ptr对象,构造出来的weak_ptr对象与shared_ptr对象管理同一个资源,但不会增加这块资源对应的引用计数。

weak_ptr基本上很少使用,这里不做详细介绍。

C++11和boost中智能指针的关系:

①C++98中产生了第一个智能指针auto_ptr。


②C++boost给出了更实用的scoped_ptr、shared_ptr和weak_ptr。


③C++TR1,引入了boost中的shared_ptr等。不过注意的是TR1并不是标准版。


④C++11,引入了boost中的unique_ptr、shared_ptr和weak_ptr。注意,unique_ptr对应的就是boost中的scoped_ptr,并且这些智能指针的实现原理是参考boost中实现的。

boost库是为C++语言标准库提供扩展的一些C++程序库的总称,boost库社区建立的初衷之一就是为C++的标准化工作提供可供参考的实现,比如在送审C++标准库TR1中,就有十个boost库成为标准库的候选方案。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Super.Bear

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值