modern c++的写法思考之智能指针

现代c++的演变越来越去指针化,智能指针的完善,目标就是让开发者可以不再管理内存的释放问题,就再也不用malloc/free,new/delete之类了。智能指针包括unique_ptr,shared_ptr,weak_ptr,使用时引用头文件#include <memory>。

unique_ptr的使用,罗列起来比较琐碎:

class Student
{
public:
    Student() {
        cout << "constructor" << endl;
    }
    ~Student() {
        cout << "destructor" << endl;
    }
private:
    string name_;
    int age_ = 0;
};

unique_ptr<Student> create_student() {
    auto ptr = make_unique<Student>();
    return ptr;
}

int main()
{
    auto uptr = make_unique<int>(16);
    cout << *uptr << endl;
    auto uptr3 = move(uptr);  //只能move
    if (uptr) {
        cout << "uptr" << endl;
    }
    if (uptr3) {
        cout << "uptr3" << endl;
    }
    /////
    auto uptr2 = make_unique<int[]>(8); //当是数组类型时,参数为数组长度
    uptr2[0] = 100;
    cout << uptr2[0] << " " << uptr2[1] << endl;

    ////
    auto ptr = create_student();
    ptr = nullptr; //手动释放
    return 0;
}

shared_ptr是线程安全的,引用计数归零时,释放内存:

int main()
{
    auto sptr = make_shared<Student>();
    auto sptr2 = sptr;
    auto sptr3 = sptr2;
    cout << sptr.use_count() << endl;   //3
    cout << sptr2.use_count() << endl;  //3
    cout << sptr3.use_count() << endl;  //3
    sptr3 = nullptr;
    cout << sptr.use_count() << endl;   //2
    cout << sptr2.use_count() << endl;  //2
    cout << sptr3.use_count() << endl;  //0
    return 0;
}

weak_ptr用得不多,它大体解决两个问题:

1. shared_ptr指向的对象随时可能会释放,采用弱引用后,对象的生命会延续到该弱引用释放为止

int main()
{
    auto sptr = make_shared<Student>();
    weak_ptr<Student> wptr = sptr;
    cout << wptr.use_count() << " " << wptr.expired() << endl; //1 0
    auto sptr2 = wptr.lock();
    cout << wptr.use_count() << " " << wptr.expired() << endl; //2 0
    sptr = nullptr;
    cout << wptr.use_count() << " " << wptr.expired() << endl; //1 0
    if (sptr2) {
        cout << "available" << endl; //available
    }
    return 0;
}

2. 解决循环引用的释放问题

class Student
{
public:
    Student() {
        cout << "constructor" << endl;
    }
    ~Student() {
        cout << "destructor" << endl;
    }
    void set_st(shared_ptr<Student>& st) {
        st_ = st;
    }
    void set_wst(shared_ptr<Student>& wst) {
        wst_ = wst;
    }
private:
    string name_;
    int age_ = 0;
    shared_ptr<Student> st_;
    weak_ptr<Student> wst_;
};
int main()
{
    auto sptr = make_shared<Student>();
    sptr->set_st(sptr);  //循环引用
    return 0;
}

执行该代码会发现,对象并没有释放,也就是出现了内存泄漏。使用弱引用就可以正常释放,因为weak_ptr是不会修改引用计数的:

int main()
{
    auto sptr = make_shared<Student>();
    sptr->set_wst(sptr);
    return 0;
}

 

发表于 2018年10月12日 15:36   评论:0   阅读:2026  



回到顶部

首页 | 关于我 | 关于本站 | 站内留言 | rss
python logo   django logo   tornado logo