欢迎访问我的博客首页。
智能指针
1. shared_ptr
shared_ptr 的计数器是线程安全的。
#include <mutex>
template <typename T>
class Shared_ptr {
public:
// 1.无参构造函数。
Shared_ptr()
: m_ptr(nullptr)
, m_count(new size_t(0))
, m_mutex(new std::mutex) {}
// 2.有参构造函数(裸指针)。
Shared_ptr(T *sptr)
: m_ptr(sptr)
, m_mutex(new std::mutex) {
if (sptr) {
m_count = new size_t(1);
} else {
m_count = new size_t(0);
}
}
// 3.拷贝构造函数(浅拷贝)。
Shared_ptr(const Shared_ptr &sptr)
: m_ptr(sptr.m_ptr)
, m_count(sptr.m_count)
, m_mutex(sptr.m_mutex) {
// 用 m_ptr = nullptr 的智能指针初始化另一智能指针,计数器不应改变。
if (m_ptr != nullptr)
// 改变 *m_count 没有改变 m_count 所以形参为 const。
(*m_count)++;
}
// 4.移动构造函数。
Shared_ptr(Shared_ptr &&sptr)
: m_ptr(sptr.m_ptr)
, m_count(sptr.m_count)
, m_mutex(sptr.m_mutex) {
sptr.set_ptr(nullptr);
sptr.set_count(nullptr);
sptr.set_mutex(nullptr);
}
// 5.移动赋值运算符重载。
Shared_ptr &operator=(Shared_ptr &&sptr) {
m_ptr = sptr.m_ptr;
m_count = sptr.m_count;
m_mutex = sptr.m_mutex;
sptr.set_ptr(nullptr);
sptr.set_count(nullptr);
sptr.set_mutex(nullptr);
return *this;
}
// 6.赋值运算符重载(浅拷贝)。
Shared_ptr &operator=(const Shared_ptr &sptr) {
if (this == &sptr)
return *this;
// 与所指对象切断连系。
if (m_ptr != nullptr) {
m_mutex->lock();
(*m_count) -= 1;
m_mutex->unlock();
if (*m_count == 0) {
delete m_ptr;
m_ptr = nullptr;
m_count = nullptr;
m_mutex = nullptr;
}
}
// 与新对象建立连系。
m_ptr = sptr.m_ptr;
m_count = sptr.m_count;
m_mutex = sptr.m_mutex;
// 用 m_ptr = nullptr 的智能指针初始化另一智能指针,计数器不应改变。
if (m_ptr != nullptr) {
m_mutex->lock();
(*m_count) += 1;
m_mutex->unlock();
}
return *this;
}
// 7.重载操作符:判断是否为0、NULL。
bool operator==(const int b) { return m_ptr == 0; }
bool operator!=(const int b) { return m_ptr != 0; }
// 7.重载操作符:判断是否为nullptr。
bool operator==(const nullptr_t &b) { return m_ptr == b; }
bool operator!=(const nullptr_t &b) { return m_ptr != b; }
// 7.重载操作符:判断两个智能指针是否指向同一个对象。
bool operator==(const Shared_ptr &b) { return m_ptr == b.m_ptr; }
bool operator!=(const Shared_ptr &b) { return m_ptr != b.m_ptr; }
// 7.重载布尔值操作符:if(x)判断是否为空指针。
operator bool() { return m_ptr == nullptr; }
// 8.获取裸指针。
T *get() { return m_ptr; }
// 9.箭头运算符:获取裸指针所指对象的成员。
T *operator->() { return m_ptr; }
// 10.解引用运算符:获取裸指针所指对象。
T &operator*() { return *m_ptr; }
// 11.是否独占对象。
bool unique() {
// 移动构造函数和移动赋值函数会使所有成员指针置空。
return !m_ptr || *m_count == 1;
}
// 12.获取共享数量。
size_t use_count() {
// 移动构造函数和移动赋值函数会使所有成员指针置空。
return m_count ? *m_count : 0;
}
// 13.与另一个智能指针交换。
void swap(Shared_ptr &sptr) { std::swap(*this, sptr); }
// 14.析构函数。
~Shared_ptr() {
// 移动构造函数和移动赋值函数会使所有成员指针置空。
if (m_count != nullptr) {
if (*m_count > 0) {
m_mutex->lock();
(*m_count)--;
m_mutex->unlock();
}
if (*m_count == 0) {
delete m_ptr;
m_ptr = nullptr;
m_count = nullptr;
m_mutex = nullptr;
}
}
}
private:
void set_ptr(T *m_ptr) { this->m_ptr = m_ptr; }
void set_count(size_t *m_count) { this->m_count = m_count; }
void set_mutex(std::mutex *m_mutex) { this->m_mutex = m_mutex; }
private:
T *m_ptr;
size_t *m_count;
std::mutex *m_mutex;
};
template <typename T, typename... Args>
// 返回值不能是引用类型。
Shared_ptr<T> Make_shared(Args &&...args) {
Shared_ptr<T> s_ptr(new T(std::forward<Args>(args)...));
return s_ptr;
}
本文详细介绍了C++中的shared_ptr智能指针,包括其构造方法(包括无参、有参、浅拷贝和移动构造),重载操作符,独占性检查,使用计数,make_shared的用法以及析构时的行为。着重强调了线程安全性和计数器管理机制。
1204

被折叠的 条评论
为什么被折叠?



