C++11四种智能指针

13 篇文章 0 订阅

智能指针

使用智能指针

auto_ptr,unique_ptr,shared_ptr都定义了类似指针的对象,可以将new获得(直接或间接)的地址赋给这种对象。当智能指针对象过期时,其析构函数将使用delete 来释放内存。
在这里插入图片描述
创建使用智能指针,包含头文件
在这里插入图片描述
throw()意味着构造函数不会引发异常,与auto_ptr一样,throw也被抛弃。
auto_ptr pd (new double);

#include <iostream>
#include<string>
#include<memory>
using namespace std;

class Report {
private:
    string str;
public:
    Report(const string s) :str(s) { cout << str << " created \n"; }
    ~Report()
    {
        cout << str << " delete \n";
    }
    void comment() const { cout << str << endl; }
};
int main()
{
    std::cout << "Hello World!\n";
    {
        auto_ptr<Report> ps(new Report("use auto"));
        ps->comment();
    }
    {
        shared_ptr<Report> ps(new Report("use share"));
        ps->comment();
    }
    {
        unique_ptr<Report> ps(new Report("use unique"));
        ps->comment();
    }
}

  1. 所有智能指针类都有一个explicit构造函数,该构造函数将指针作为参数。因此不需要自动将指针转为智能指针对象。
    shared_ptr pd;
    double* p_reg = new double;
    pd = p_reg; // not allowed
    pd = shared_ptr(p_reg); //ok
    shared_ptr ps = p_reg; // not allowed
    shared_ptr ps (p_reg); //ok
  2. 智能指针与常规指针类似,可以 ps-> 或者*ps
  3. 智能指针应该避免
    string s(“safsgag”);
    shared_ptr ps(&s);
    ps过期时,程序将把delete运算符用于非堆的内存

智能指针注意事项

实际上有四种,还有weak_ptr,为何摒弃auto_prt;
auto_ptr ps(new string(“sssss”));
auto_ptr pd ;
ps = pd;
如果ps和pd是常规指针,则两个指针将指向同一个string对象。这样程序将试图删除同一个对象两次,一次是ps过期,一次是pd过期。避免这种问题方法有很多。
1.定义赋值运算,使之执行深度赋值。这样两个指针将指向不同的对象,其中的一个对象是另一个对象的副本
2.建立所有权概念,对于特定的对象,只有一个智能指针能拥有它。这样只有拥有对象的智能指针的析构函数会删除该对象。然后让赋值操作转让所有权,这就是用于auto和unique的策略,但后者更严格。
3.创建更高的指针,跟踪引用特定对象的智能指针数。这称为引用计数。赋值时,计数+1,对象过期时-1。仅当最后一个对象过期时,才调用delete。(shared_ptr)
4. 不适用auto_ptr的例子

int main()
{
    auto_ptr<string> a[4] =
    {
        auto_ptr<string>(new string("088")),
        auto_ptr<string>(new string("134")),
        auto_ptr<string>(new string("5667")),
        auto_ptr<string>(new string("145125")),
    };
    auto_ptr<string> pa;
    pa = a[2];  //若使用unique_ptr 编译不通过,此处报错
    //此处将所有权从a【2】给pa,a【2】不再引用该字符串。在 auto_ptr放弃对象所有权后,便可能使用它来访问该对象,此时*a【2】为空指针
    cout << "________________________\n";
    for (auto p : a)
        cout << *p << endl;     //打印5667异常退出 ,若改用shared_ptr则不会;
                                
    cout << "the is " << *pa << endl;
}

unique_ptr优于auto_ptr

  	auto_ptr<string>p1(new string("088"));
    auto_ptr<string>p2;
    p2 = p1;   //p2接管string对象所有权后,p1的所有权将被剥夺。可以防止析构同一个对象两次,但是此时p1指向无效的数据,使用p1会出现错误

    unique_ptr<string>p1(new string("088"));
    unique_ptr<string>p2;
    p2 = p1;   //此时编译器将报错
  1. 函数中可以
unique_ptr<string> demo(const char* s)
{
    unique_ptr<string> tmp(new string(s));
    return tmp;
}
int main()
{
    unique_ptr<string> ps;
    ps = demo("okl");
    //允许demo返回临时的,然后ps接管了,ps拥有对象的所有权,临时的将很快销毁,没有机会使用无效的数据
}

总之,程序试图将一个unique_ptr赋给另一个时,如果源unique_ptr是一个临时右值,编译器允许这样;但源unique_ptr存在很长一段时间,则编译器禁止。
unique_ptr p1 (new string(“hello”));
unique_ptr ps;
ps = p1; // no 此时p1悬挂,危险。非要这样 ,不要使用智能指针
unique_ptr p2;
p2 = unique_ptr (new string(“hello”)); //ok 调用构造,临时变量很快被销毁
2. c++有一个标准库函数std::move(),能够将一个unique_ptr赋给另一个。

unique_ptr<string> demo(const char* s)
{
    unique_ptr<string> tmp(new string(s));
    return tmp;
}
int main()
{
    unique_ptr<string> ps1,ps2;
    ps1 = demo("wttkk");
    ps2 = move(ps1);
    ps1 = demo("wt");
    cout << *ps1 << endl;
    cout << *ps2 << endl;
}
  1. unique_ptr还有另一个优点,它有一个可用于数组的变体。
    auto_ptr只能和new一起使用
    unique_ptr<double []>pad(new double(5));
    注意:智能指针只适用于用new或new【】分配的内存。

选择智能指针

1.如果程序使用多个指向同一对象的指针,应选择shared_ptr.这样的情况包括:有一个指针数组,并使用一些辅助指针来标识特定的元素,如最大和最小;两个对象包含都指向第三个元素的指针;STL容器包含指针。若编译器没有shared_ptr.使用Boost库提供的shared_ptr.
2.如果程序不需要多个指向同一个对象的指针,则可以使用 unique_ptr。如果函数使用new分配内存,并返回指向该内存的地址,将其声明为unique_ptr是不错的选择。这样所有权将转让给接受返回值的 unique_ptr,而该智能指针将负责调用delete。可将 unique_ptr存到容器中,只要不调用将一个 unique_ptr复制或赋给另一个的方法或算法(如sort())。
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值