计数指针 std::shared_ptr

shared_ptr 共享指针

  • shared_ptr 计数指针称为共享指针,可以共享数据。
  • shared_ptr 创建了一个计数器与类对象所指的内存相关联
  • Copy 之后计数器加一,销毁之后计数器减一。
  • 计数器 API 接口为 :use_count()

测试代码:

#include <iostream>
#include <memory>

class Stu {
    
    std::string m_name;

public:
    Stu() {
        this->m_name = "stuTemp";
        std::cout << "无参构造" << std::endl;
    }
    Stu(std::string name) :m_name(name) {
        std::cout << "有参构造" << std::endl;
    }
    ~Stu() {
        std::cout << "析构" << std::endl;
    }

    void printStuName() const {
        std::cout << this->m_name << std::endl;
    }
};

int main() {

    // 常量类型
    std::shared_ptr<int> i_p1 = std::make_shared<int>(10);
    std::cout << "value:" << *i_p1 << std::endl;
    std::cout << "use count:" << i_p1.use_count() << std::endl;

    std::shared_ptr<int> i_p2 = i_p1;
    std::cout << "i_p1 use count:" << i_p1.use_count() << std::endl;
    std::cout << "i_p2 use count:" << i_p2.use_count() << std::endl;

    *i_p1 = 20;
    std::cout << "i_p1 value:" << *i_p1 << std::endl;
    std::cout << "i_p2 value:" << *i_p2 << std::endl;

    //i_p1 = nullptr;
    i_p2 = nullptr;
    std::cout << "i_p1 use count:" << i_p1.use_count() << std::endl;
    std::cout << "i_p2 use count:" << i_p2.use_count() << std::endl;

    // 自定义类型
    std::shared_ptr<Stu> s_p1 = std::make_shared<Stu>("FF");
    std::cout << "s_p1 use count:" << s_p1.use_count() << std::endl;
    std::shared_ptr<Stu> s_p2 = s_p1;
    std::shared_ptr<Stu> s_p3 = s_p1;
    std::cout << "s_p1 use count:" << s_p1.use_count() << std::endl;
    std::cout << "s_p2 use count:" << s_p2.use_count() << std::endl;
    std::cout << "s_p3 use count:" << s_p3.use_count() << std::endl;

    s_p1.reset(); // 只有清空的是 0
    std::cout << "s_p1 use count:" << s_p1.use_count() << std::endl;
    std::cout << "s_p2 use count:" << s_p2.use_count() << std::endl;
    std::cout << "s_p3 use count:" << s_p3.use_count() << std::endl;

    return 0;
}

运行结果:

被销毁的指针 use_count 被清零 


 shared_ptr 与 函数调用

传入值的方式:

  • copy的方式
  • 函数内部计数器加一

传入引用的方式:

  • const 限制传入其指向

函数返回值的方式:

  • 链式调用

测试代码: 

#include <iostream>
#include <memory>

class Stu {
    
    std::string m_name;

public:
    Stu() {
        this->m_name = "stuTemp";
        std::cout << "无参构造" << std::endl;
    }
    Stu(std::string name) :m_name(name) {
        std::cout << "有参构造" << std::endl;
    }
    ~Stu() {
        std::cout << "析构" << std::endl;
    }

    void printStuName() const {
        std::cout << this->m_name << std::endl;
    }

    void setStuName(std::string name) {
        this->m_name = name;
    }
};

void doWithPassValue(std::shared_ptr<Stu> s) {
    s->setStuName("aa");
    s->printStuName(); // aa
    std::cout << "value s use count:" << s.use_count() << std::endl; // 2
}

void doWithPassRef(const std::shared_ptr<Stu>& s) {
    s->setStuName("bb");
    s->printStuName(); // bb
    std::cout << "reference s use count" << s.use_count() << std::endl; // 1
}

std::shared_ptr<Stu> doWithPassReturn(const std::string str) {
    std::shared_ptr<Stu> s = std::make_shared<Stu>(str);
    return s;
}

int main() {

    // 1、by value
    std::shared_ptr<Stu> s_p1 = std::make_shared<Stu>("AA");
    doWithPassValue(s_p1);
    s_p1->printStuName(); // aa
    std::cout << "s_p1 use count:" << s_p1.use_count() << std::endl; // 1

    // 2、by reference
    std::shared_ptr<Stu> s_p2 = std::make_shared<Stu>("BB");
    doWithPassRef(s_p2);
    s_p2->printStuName(); // bb
    std::cout << "s_p2 use count:" << s_p2.use_count() << std::endl; // 1

    // 3、by return value
    //doWithPassReturn("CC")->printStuName();
    std::shared_ptr<Stu> s_p3 = doWithPassReturn("CC");
    s_p3->printStuName();
    std::cout << "s_p3 use count:" << s_p3.use_count() << std::endl; // 1


    std::cout << "-----------" << std::endl;

    return 0;
}

运行结果:


shared_ptr 与 unique_ptr 

  • shared_ptr 不可以转换为 unique_ptr。
  • unique_ptr 可以通过 move 的方法 转化为 shared_ptr。
  • 函数返回值可以设计为 返回 unique_ptr 类型,unique_ptr 可以转化为 shared_ptr。提高代码复用度,随时更改为 shared_ptr。

测试代码: 

#include <iostream>
#include <memory>

class Stu {
    
    std::string m_name;

public:
    Stu() {
        this->m_name = "stuTemp";
        std::cout << "无参构造" << std::endl;
    }
    Stu(std::string name) :m_name(name) {
        std::cout << "有参构造" << std::endl;
    }
    ~Stu() {
        std::cout << "析构" << std::endl;
    }

    void printStuName() const {
        std::cout << this->m_name << std::endl;
    }

    void setStuName(std::string name) {
        this->m_name = name;
    }
};

std::unique_ptr<Stu> getUniquePtr() {
    std::unique_ptr<Stu> s = std::make_unique<Stu>("AA");
    return s;
}

int main() {

    // move 方法
    std::unique_ptr<Stu> u_p1 = std::make_unique<Stu>("FF");
    std::shared_ptr<Stu> s_p1 = std::move(u_p1); // 转移所有权

    std::cout << s_p1.use_count() << std::endl;


    // function return
    // 返回 unique_ptr 接受可以使用 shared_ptr
    std::shared_ptr<Stu> s_p2 = getUniquePtr();
    if (s_p2) {
        s_p2->printStuName();
        std::cout << "s_p2 use count:" << s_p2.use_count() << std::endl;
    }
    return 0;
}

运行结果:

unique_ptr 在使用上是很方便的,用作函数返回值可以用 shared_ptr 去接受,也可以通过 move 方法将所有权转换到 shared_ptr 上,原本的 unique_ptr 经过转移就不可以再使用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值