auto_ptr(隐患,可能释放2次), shared_ptr, unique_ptr, weak_ptr。
详细的理论可以大家可以参考其他资料,这里一些代码片段方便自己平时工作查阅。
shared_ptr
#include <iostream>
#include <memory>
#include <string>
class TestA
{
public:
TestA(int n, std::string name): member(n), m_name(name){};
void show() {
std::cout << "Init class, id: " << member << " name: " << m_name << std::endl;
}
void update_name(std::string name) {
m_name = name;
}
private:
int member;
std::string m_name;
};
void pass_by_value(std::shared_ptr<TestA> a)
{
std::cout << "------------------------------------------------------------- \n";
std::cout << "pass by value function \n";
a->show();
std::cout << "use count: " << a.use_count() << std::endl;
std::cout << "------------------------------------------------------------- \n";
}
void pass_by_ref(std::shared_ptr<TestA> &a)
{
std::cout << "------------------------------------------------------------- \n";
std::cout << "pass by ref function \n";
a->show();
std::cout << "use count: " << a.use_count() << std::endl;
std::cout << "------------------------------------------------------------- \n";
}
std::shared_ptr<TestA> get_share_ptr()
{
std::shared_ptr<TestA> local = std::make_shared<TestA>(10, "local");
return local;
}
int main()
{
// 构建方式1
std::shared_ptr<TestA> ptr1 = std::make_shared<TestA>(1, "bobo");
ptr1->show();
// 查看引用计数
std::cout << "use count: " << ptr1.use_count() << std::endl;
// 赋值
std::shared_ptr<TestA> ptr2 = ptr1;
auto ptr3 = ptr1;
std::cout << "ptr1 use count: " << ptr1.use_count() << std::endl;
std::cout << "ptr2 use count: " << ptr2.use_count() << std::endl;
std::cout << "ptr3 use count: " << ptr3.use_count() << std::endl;
// 删除某一个指针观察引用计数
ptr2 = nullptr; // ptr2.reset();
std::cout << "ptr1 use count: " << ptr1.use_count() << std::endl;
std::cout << "ptr3 use count: " << ptr3.use_count() << std::endl;
// 因为共享某一块内存,可以观察值
std::cout << "------------------------------------------------------------- \n";
ptr1->update_name("tom");
ptr1->show();
ptr3->show();
std::cout << "------------------------------------------------------------- \n";
pass_by_value(ptr1);
std::cout << "ptr1 use count: " << ptr1.use_count() << std::endl;
std::cout << "ptr3 use count: " << ptr3.use_count() << std::endl;
std::cout << "------------------------------------------------------------- \n";
pass_by_ref(ptr1);
std::cout << "ptr1 use count: " << ptr1.use_count() << std::endl;
std::cout << "ptr3 use count: " << ptr3.use_count() << std::endl;
std::cout << "------------------------------------------------------------- \n";
std::shared_ptr<TestA> ptr4 = get_share_ptr();
std::cout << "ptr4 use count: " << ptr4.use_count() << std::endl;
std::cout << "Finished! \n";
return 0;
}
unique_ptr
#include <iostream>
#include <memory>
class TestA
{
public:
TestA(int n): member(n){};
void show() {
std::cout << "init class, n: " << member << std::endl;
}
private:
int member;
};
void pass_by_value(std::unique_ptr<TestA> a)
{
std::cout << "pass by value \n";
a->show();
}
void print_by_ref(std::unique_ptr<TestA> &a)
{
std::cout << "print by ref \n";
a->show();
a.reset(); // 清空指针
}
void print_by_ref_const(const std::unique_ptr<TestA> &a)
{
std::cout << "print by ref \n";
a->show();
// a.reset(); // const 引用,不可以修改值
}
std::unique_ptr<TestA> return_by_value()
{
std::cout << "return by value function \n";
std::unique_ptr<TestA> local = std::make_unique<TestA>(6);
return local;
}
int main()
{
// 构造方式1
TestA *a_ptr = new TestA(1);
std::unique_ptr<TestA> a_unique_ptr{a_ptr};
a_unique_ptr->show();
// 构造方式2
std::unique_ptr<TestA> unique_ptr_02{new TestA(2)};
unique_ptr_02->show();
// 构造方式3
std::unique_ptr<TestA> unique_ptr_03 = std::make_unique<TestA>(3);
unique_ptr_03->show();
// 函数传递值
std::unique_ptr<TestA> unique_pass_by_value = std::make_unique<TestA>(4);
pass_by_value(std::move(unique_pass_by_value)); // 转换为右值
// 传递引用
std::unique_ptr<TestA> unique_pass_by_ref = std::make_unique<TestA>(5);
print_by_ref(unique_pass_by_ref);
// 函数返回值
std::unique_ptr<TestA> return_by_value_ptr{std::move(return_by_value())};
return_by_value_ptr->show();
return 0;
}
补充
1. weak_ptr用来避免shared_ptr互相引用无法释放。lock方法可以查看对象是否释放,设计本身就是服务于shared_ptr,核心功能就是不增加引用计数。
class Test
{
private:
std::shared_ptr<Test> m_friend; // 为了避免循环引用,改为weak_ptr即可
}
2. 不可以将shared_ptr转换为unique_ptr。 unique_ptr可以转换为shared_ptr,通过std::move。
3. 引用计数和指向变量的指针作为一种临界资源,如果不加锁,那么在多线程情况下会出现线程安全问题。