博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++11 智能指针
阅读量:6517 次
发布时间:2019-06-24

本文共 3046 字,大约阅读时间需要 10 分钟。

hot3.png

    C++11提供了三个智能指针,std::shared_ptr,std::unique_ptr,std::weak_ptr。最常用的是shared_ptr和unique_ptr。

    (1)std::shared_ptr

            shared_ptr是共享指针,通过在控制块中增加引用计数的方式实现多个指针指向同一个对象。每当拷贝构造或者拷贝赋值时,对象的引用计数都会+1,每当指针对象析构时,引用计数-1,直到引用计数为0,释放实际指针对象。

            std::shared_ptr<T> sp(new T()) 形式声明效率上没有 std::shared_ptr<T> sp = std::make_shared<T>()高,因为前一种声明方式在实现上需要new两次(一次是new T, 一次是 new 控制结构),而后者在实现上一般都是一次。

示例如下:

#include <iostream>

#include <memory>

int main() {

    {
        std::shared_ptr<int> sp1;

        {

            std::shared_ptr<int> sp2(new int(10));
            sp1 = sp2;
            std::cout << "sp1.count=" << sp1.use_count() << std::endl;    // use_count为2
        }
        std::cout << "sp1.count=" << sp1.use_count() << std::endl;        // use_count为1
    }

    return 0;

}

 

    2,std::unique_ptr

        unique_ptr顾名思义,只允许一个指针指向同一个对象。unique_ptr通过禁止拷贝构造函数和拷贝赋值运算符到达无法让多个指针指向同一个对象的目的。unique_ptr通过移动构造函数和移动赋值运算符达到指针对象资源转移的目的(保证某一时刻只有一个指针指向该对象)。

        同样,std::unique_ptr<T> sp(new T()) 形式声明效率上没有 std::unique_ptr<T> sp = std::make_unique<T>()高,因为前一种声明方式在实现上需要new两次(一次是new T, 一次是 new 控制结构),而后者在实现上一般都是一次。

示例如下:

#include <iostream>

#include <memory>

int main() {

    std::unique_ptr<int> sp1(new int(10));
//    std::unique_ptr<int> sp2 = sp1;                    // 编译错误,拷贝构造函数 deleted
    std::unique_ptr<int> sp2 = std::move(sp1);    // ok,使用移动构造函数,实现资源转移

    return 0;

}
 

    3,std::weak_ptr

        std::shared_ptr在循环引用的情况下会有内存泄漏的问题,示例如下:

#include <iostream>

#include <memory>

class Child;

class Parent;

class Parent {

private:
    std::shared_ptr<Child> ChildPtr;

public:

    void setChild(std::shared_ptr<Child> child) {
        this->ChildPtr = child;
    }

    ~Parent() {}

};

class Child {

private:
    std::shared_ptr<Parent> ParentPtr;

public:

    void setPartent(std::shared_ptr<Parent> parent) {
        this->ParentPtr = parent;
    }

    ~Child() {}

};

int main() {

    std::weak_ptr<Parent> wpp;
    std::weak_ptr<Child> wpc;
    {
        std::shared_ptr<Parent> p(new Parent);
        std::shared_ptr<Child> c(new Child);
        p->setChild(c);
        c->setPartent(p);
        wpp = p;
        wpc = c;
        std::cout << p.use_count() << std::endl; // 2
        std::cout << c.use_count() << std::endl; // 2
    }
    std::cout << wpp.use_count() << std::endl;  // 1
    std::cout << wpc.use_count() << std::endl;  // 1
    return 0;
}
    说明:本质上来说,由于循环相互引用,导致双方都没有减少对方的引用计数,导致双方资源都没有释放掉。

    std::weak_ptr提供了一种资源监视的方法:使用weak_ptr指向一个shared_ptr,并不会增加对象的引用计数,但是可以访问shared_ptr的控制块结构。解决上述循环引用问题的示例代码如下:

    

#include <iostream>

#include <memory>

class Child;

class Parent;

class Parent {

private:
    std::shared_ptr<Child> ChildPtr;

public:

    void setChild(std::shared_ptr<Child> child) {
        this->ChildPtr = child;
    }

    ~Parent() {}

};

class Child {

private:
//    std::shared_ptr<Parent> ParentPtr;
    std::weak_ptr<Parent> ParentPtr;

public:

    void setPartent(std::shared_ptr<Parent> parent) {
        this->ParentPtr = parent;
    }

    ~Child() {}

};

int main() {

    std::weak_ptr<Parent> wpp;
    std::weak_ptr<Child> wpc;
    {
        std::shared_ptr<Parent> p(new Parent);
        std::shared_ptr<Child> c(new Child);
        p->setChild(c);
        c->setPartent(p);
        wpp = p;
        wpc = c;
        std::cout << p.use_count() << std::endl;   // 1
        std::cout << c.use_count() << std::endl;   // 2
    }
    std::cout << wpp.use_count() << std::endl;  // 0
    std::cout << wpc.use_count() << std::endl;  // 0
    return 0;
}
 

转载于:https://my.oschina.net/yepanl/blog/2208153

你可能感兴趣的文章
Coding and Paper Letter(十七)
查看>>
Visual Studio 的码云扩展 V1.0.85 发布
查看>>
ES6特性之:模板字符串
查看>>
从零玩转jQuery-属性相关
查看>>
Unity导航系统Navigation使用教程
查看>>
Unity C#图片转换二进制流、字符串互转
查看>>
NIO框架入门(四):Android与MINA2、Netty4的跨平台UDP双向通信实战
查看>>
Anroid文章推荐
查看>>
YAML文件中在单一文件中区分多个文件
查看>>
Android开发小技巧之商品属性筛选与商品筛选
查看>>
Netflix如何节省92%视频编码成本?
查看>>
ios兼容iphonex刘海屏解决方案
查看>>
Virtual Box 工具栏(菜单栏)消失的解决方法
查看>>
HBuilder使用夜神模拟器调试Android应用
查看>>
公司的一个面试题:如何用css让一个容器水平垂直居中?
查看>>
大数据教程(一)—— Hadoop集群坏境搭建配置
查看>>
汇聚年度最佳技术与实践 OpenStack Days China大会7月在京举行
查看>>
第119天:移动端:CSS像素、屏幕像素和视口的关系
查看>>
数据库两大神器【索引和锁】
查看>>
linux查找目录下的所有文件中是否含有某个字符串
查看>>