指针指针的实现
上一篇文章简单介绍了一下智能指针,这次我们简单讲解一下实现和具体的例子,及分析。
1. Unique_Ptr
实现
unique_ptr
是一种独占所有权的智能指针,不允许拷贝,只允许移动。它确保资源只被一个所有者拥有,并在所有者被销毁时自动释放资源。
实现:
// 默认删除器
struct DefaultDeleter {
template <typename T>
void operator()(T* ptr) const {
delete ptr;
}
};
// UniquePtr 类模板
template <typename T, typename Deleter = DefaultDeleter>
class UniquePtr {
private:
T* ptr;
public:
// 默认构造函数,初始化为 nullptr
constexpr UniquePtr()noexcept
: ptr(nullptr)
{}
// 从指针构造
explicit constexpr UniquePtr(T* p) noexcept
: ptr(p)
{}
// 禁止拷贝构造
UniquePtr(const UniquePtr& other) = delete;
// 禁止拷贝赋值
UniquePtr& operator=(const UniquePtr& other) = delete;
// 移动构造函数
constexpr UniquePtr(UniquePtr&& other) noexcept
: ptr(other.ptr) {
other.ptr = nullptr;
}
// 移动赋值运算符
UniquePtr& operator=(UniquePtr&& other) noexcept {
if (this != &other) {
reset(other.ptr);
other.ptr = nullptr;
}
return *this;
}
// 析构函数,释放资源
~UniquePtr() {
reset();
}
// 重置指针
void reset(T* p = nullptr) {
if (ptr != p) {
Deleter()(ptr);
ptr = p;
}
}
// 释放所有权
T* release() noexcept {
T* ret = ptr;
ptr = nullptr;
return ret;
}
// 获取指针
T* get() const noexcept {
return ptr;
}
// 重载解引用运算符
T& operator*() const {
return *ptr;
}
// 重载箭头运算符
T* operator->() const {
return ptr;
}
// 转换为 bool
explicit operator bool() const noexcept {
return ptr != nullptr;
}
// 禁止隐式转换为其他指针类型
template <typename U>
operator U*() const = delete;
};
使用例子:
int main() {
UniquePtr<int> up1(new int(42));
cout << "*up1 = " << *up1 << endl;
UniquePtr<int> up2 = move(up1);
if (!up1) {
cout << "up1 is empty after move." <<endl;
}
cout << "*up2 = " << *up2 << endl;
up2.reset();
if (!up2) {
cout << "up2 is empty after reset." << endl;
}
return 0;
}
//输出
*up1 = 42
up1 is empty after move.
*up2 = 42
up2 is empty after reset.
2. Shared_Ptr
实现
shared_ptr
是一种共享所有权的智能指针,使用引用计数来管理对象的生命周期。多个 shared_ptr
可以共享同一个对象,当最后一个 shared_ptr
被销毁时,资源被释放。
template <typename T>
class SharedPtr {
private:
T* ptr; // 原始指针
size_t* count; // 引用计数
public:
// 构造函数
explicit SharedPtr(T* p = nullptr)
: ptr(p)
, count(new size_t(1)) {
if (p == nullptr) {
*count = 0;
}
}
// 拷贝构造函数
SharedPtr(const SharedPtr<T>& other)
: ptr(other.ptr)
, count(other.count) {
if (ptr) {
(*count)++;
}
}
// 析构函数
~SharedPtr() {
release();
}
// 拷贝赋值运算符
SharedPtr<T>& operator=(const SharedPtr<T>& other) {
if (this != &other) {
release();
ptr = other.ptr;
count = other.count;
if (ptr) {
(*count)++;
}
}
return *this;
}
// 解引用运算符
T& operator*() const {
return *ptr;
}
// 箭头运算符
T* operator->() const {
return ptr;
}
// 获取引用计数
size_t use_count() const {
return *count;
}
// 获取原始指针
T* get() const {
return ptr;
}
// 重置指针
void reset(T* p = nullptr) {
release();
ptr = p;
count = new size_t(1);
if (p == nullptr) {
*count = 0;
}
}
private:
// 释放资源
void release() {
if (ptr && --(*count) == 0) {
delete ptr;
delete count;
ptr = nullptr;
count = nullptr;
}
}
};
举例:
class MyClass {
public:
MyClass()
{
cout << "MyClass constructed\n";
}
~MyClass()
{
cout << "MyClass destroyed\n";
}
void print()
{
cout << "Hello from MyClass\n";
}
};
int main() {
// 创建shared_ptr
SharedPtr<MyClass> ptr1(new MyClass());
cout << "Use count: " << ptr1.use_count() << endl; //输出1
{
// 拷贝构造
SharedPtr<MyClass> ptr2 = ptr1;
cout << "Use count: " << ptr1.use_count() << endl; // 输出2
ptr2->print();
}
cout << "Use count: " << ptr1.use_count() << endl; // 输出1
// 赋值操作
SharedPtr<MyClass> ptr3;
ptr3 = ptr1;
cout << "Use count: " << ptr1.use_count() << endl; //输出 2
// 重置指针
ptr1.reset(new MyClass());
cout << "Use count: " << ptr1.use_count() << endl; //输出 1
return 0;
}
3. Weak_Ptr
实现
weak_ptr
是一种不拥有所有权的智能指针,用于配合 shared_ptr
使用,以解决循环引用问题。weak_ptr
不影响引用计数,但可以通过 lock()
方法获取一个 shared_ptr
,以访问对象。
实现代码:
template <typename T>
class WeakPtr {
private:
T* ptr; // 指向被管理的对象
size_t* shared_count; // 指向 shared_ptr 的引用计数
size_t* weak_count; // 指向 weak_ptr 的引用计数
public:
// 默认构造函数
WeakPtr()
: ptr(nullptr)
, shared_count(nullptr)
, weak_count(nullptr)
{}
// 从 shared_ptr 构造
WeakPtr(const SharedPtr<T>& shared)
: ptr(shared.get())
,shared_count(shared.get_count_ptr())
,weak_count(new size_t(1)) {
if (shared_count) {
(*weak_count)++;
}
}
// 拷贝构造函数
WeakPtr(const WeakPtr<T>& other)
: ptr(other.ptr)
, shared_count(other.shared_count)
,weak_count(other.weak_count) {
if (weak_count) {
(*weak_count)++;
}
}
// 析构函数
~WeakPtr() {
release();
}
// 拷贝赋值运算符
WeakPtr<T>& operator=(const WeakPtr<T>& other) {
if (this != &other) {
release();
ptr = other.ptr;
shared_count = other.shared_count;
weak_count = other.weak_count;
if (weak_count) {
(*weak_count)++;
}
}
return *this;
}
// 从 shared_ptr 赋值
WeakPtr<T>& operator=(const SharedPtr<T>& shared) {
release();
ptr = shared.get();
shared_count = shared.get_count_ptr();
weak_count = new size_t(1);
if (shared_count) {
(*weak_count)++;
}
return *this;
}
// 尝试提升为 shared_ptr
SharedPtr<T> lock() const {
if (expired()) {
return SharedPtr<T>();
}
return SharedPtr<T>(*this);
}
// 检查是否过期
bool expired() const {
return shared_count == nullptr || *shared_count == 0;
}
// 获取引用计数信息
size_t use_count() const {
return shared_count ? *shared_count : 0;
}
private:
// 释放资源
void release() {
if (weak_count && --(*weak_count) == 0) {
if (shared_count && *shared_count == 0) {
delete ptr;
delete shared_count;
}
delete weak_count;
}
}
};
这里我们得修改shared_ptr用来支持weak_ptr
修改:
template <typename T>
class SharedPtr {
// ... (之前的实现保持不变)
// 新增方法,供 WeakPtr 访问
size_t* get_count_ptr() const { return count; }
// 新增构造函数,供 WeakPtr::lock() 使用
SharedPtr(const WeakPtr<T>& weak)
: ptr(weak.ptr)
, count(weak.shared_count) {
if (count && *count > 0) {
(*count)++;
} else {
ptr = nullptr;
count = nullptr;
}
}
};
使用例子:
int main() {
// 创建 shared_ptr
SharedPtr<MyClass> shared(new MyClass());
// 创建 weak_ptr
WeakPtr<MyClass> weak = shared;
// 使用 weak_ptr
if (auto locked = weak.lock()) {
locked->print(); // 安全使用
:cout << "Use count: " << locked.use_count() << endl;
}
// 释放 shared_ptr
shared.reset();
// 检查 weak_ptr 是否过期
if (weak.expired()) {
cout << "Object has been deleted" << endl;
}
return 0;
}
实现就结束了,基本定义参考我上篇文章,如有错误还请评论区纠正。