shared_ptr.h
#pragma once
#include <atomic>
template<typename T>
class shared_ptr {
private:
T* ptr; // 指向管理的对象
std::atomic<std::size_t>* ref_count; //原子引用计数
// 释放资源
void release() {
if (ref_count && ref_count->fetch_sub(1, std::memory_order_acq_rel) == 1) {
delete ptr;
delete ref_count;
}
}
public:
// 默认构造函数
shared_ptr() : ptr(nullptr), ref_count(nullptr) {}
// 构造函数
// explicit 为了防止 shared_ptr<T> s = new int(10);
explicit shared_ptr(T* p) : ptr(p), ref_count(p ? new std::atomic<std::size_t>(1) : nullptr) {}
// 析构函数
~shared_ptr() {
release();
}
// 拷贝构造函数
shared_ptr(const shared_ptr<T>& other) : ptr(other.ptr), ref_count(other.ref_count) {
if (ref_count) {
ref_count->fetch_add(1, std::memory_order_relaxed); // 引用计数加1
}
}
// 拷贝赋值运算符
shared_ptr<T>& operator=(const shared_ptr<T>& other) {
if (this != &other) {
release();
ptr = other.ptr;
ref_count = other.ref_count;
if (ref_count) {
ref_count->fetch_add(1, std::memory_order_relaxed); // 引用计数加1
}
}
return *this;
}
// 移动构造函数
shared_ptr(shared_ptr<T>&& other) noexcept : ptr(other.ptr), ref_count(other.ref_count) {
other.ptr = nullptr;
other.ref_count = nullptr;
}
// 移动赋值运算符
shared_ptr<T>& operator=(shared_ptr<T>&& other) noexcept {
if (this != &other) {
release();
ptr = other.ptr;
ref_count = other.ref_count;
other.ptr = nullptr;
other.ref_count = nullptr;
}
return *this;
}
// 解引用运算符
T& operator*() const {
return *ptr;
}
// 指针运算符
T* operator->() const {
return ptr;
}
// 取址运算符
T* get() const {
return ptr;
}
// 引用计数
std::size_t use_count() const {
return ref_count ? ref_count->load(std::memory_order_acquire) : 0;
}
// 是否为空
bool unique() const {
return use_count() == 1;
}
// 是否有效
explicit operator bool() const {
return ptr != nullptr;
}
void reset(T* p = nullptr) {
release();
ptr = p;
ref_count = p ? new std::atomic<std::size_t>(1) : nullptr;
}
};example.cpp
#include <iostream>
#include "shared_ptr.h"
#include<thread>
#include<vector>
#include<chrono>
void test_shared_ptr_thread_safety()
{
shared_ptr<int> ptr(new int(10));
const int num_threads = 10;
std::vector<std::thread> threads;
for (int i = 0; i < num_threads; ++i)
{
threads.emplace_back([&ptr]() {
for (int j = 0; j < 10000; ++j)
{
shared_ptr<int> local_ptr(ptr);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
});
}
for (auto& thread : threads)
{
thread.join();
}
std::cout << "use_count: " << ptr.use_count() << std::endl;
if (ptr.use_count() == 1) {
std::cout << "shared_ptr is thread-safe" << std::endl;
}
else {
std::cout << "shared_ptr is not thread-safe" << std::endl;
}
}
int main()
{
shared_ptr<int> ptr1(new int(10));
std::cout << "ptr1 use_count: " << ptr1.use_count() << std::endl;
{
shared_ptr<int> ptr2(ptr1);
std::cout << "ptr2 use_count: " << ptr2.use_count() << std::endl;
}
std::cout << "ptr1 use_count: " << ptr1.use_count() << std::endl;
test_shared_ptr_thread_safety();
return 0;
}