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 经过转移就不可以再使用。