TypechoJoeTheme

至尊技术网

登录
用户名
密码

c++如何实现一个简单的智能指针_C++手写shared_ptr原理与实现,c+智能指针

2025-11-23
/
0 评论
/
41 阅读
/
正在检测是否收录...
11/23

在现代C++开发中,内存安全和资源管理是程序员必须面对的核心问题。裸指针虽然灵活,但极易引发内存泄漏、悬空指针等严重缺陷。为此,C++标准库引入了std::shared_ptr这一智能指针类型,通过引用计数机制自动管理动态对象的生命周期。理解其底层原理并尝试手动实现,不仅能加深对RAII(资源获取即初始化)思想的理解,还能提升对C++对象生命周期控制的掌控能力。

shared_ptr的核心设计思想是“共享所有权”。多个shared_ptr实例可以指向同一个堆对象,只有当最后一个指向该对象的shared_ptr被销毁时,对象才会被自动释放。这种机制依赖于一个独立的控制块(control block),其中保存着两个关键数据:一是当前指向该对象的shared_ptr数量(引用计数),二是可能存在的弱引用计数(用于weak_ptr支持,本文暂不展开)。每当一个新的shared_ptr拷贝被创建时,引用计数加一;每当一个shared_ptr析构或被赋值为其他指针时,引用计数减一。一旦引用计数归零,所管理的对象就会被delete

要实现一个简易版的shared_ptr,首先需要定义一个模板类,因为它需要适配任意类型的指针。同时,我们还需要一个辅助的控制块结构体,用来存放引用计数和实际指针。这个控制块通常由new动态分配,确保其生命周期独立于任何一个shared_ptr实例。

cpp
template
class sharedptr { private: T* ptr; // 指向管理的对象 int* refcount; // 指向引用计数的指针

// 私有构造函数,用于内部初始化
void increase() { 
    if (ref_count) ++(*ref_count); 
}

void decrease() {
    if (ref_count && --(*ref_count) == 0) {
        delete ptr;
        delete ref_count;
        ptr = nullptr;
        ref_count = nullptr;
    }
}

public:
// 构造函数:接管原始指针
explicit sharedptr(T* p = nullptr) : ptr(p), refcount(nullptr) {
if (ptr) {
ref_count = new int(1);
}
}

// 拷贝构造函数
shared_ptr(const shared_ptr& other) : ptr(other.ptr), ref_count(other.ref_count) {
    increase();
}

// 赋值操作符
shared_ptr& operator=(const shared_ptr& other) {
    if (this != &other) {
        decrease();           // 释放当前资源
        ptr = other.ptr;
        ref_count = other.ref_count;
        increase();           // 增加新目标的引用
    }
    return *this;
}

// 解引用操作
T& operator*() const { return *ptr; }
T* operator->() const { return ptr; }

// 获取原始指针
T* get() const { return ptr; }

// 当前引用计数
int use_count() const { return ref_count ? *ref_count : 0; }

// 是否唯一拥有者
bool unique() const { return use_count() == 1; }

// 析构函数
~shared_ptr() {
    decrease();
}

};

上述实现虽然简化了部分功能(如不支持自定义删除器、不处理多线程竞争),但已经完整体现了shared_ptr的核心逻辑。特别值得注意的是赋值操作中的自我赋值判断(this != &other),这是防止错误释放资源的关键。此外,在decrease()中,我们先判断ref_count是否为空,避免对空指针进行操作。

测试代码如下:

cpp
struct Test {
Test(int x) : val(x) { std::cout << "Construct " << val << "\n"; }
~Test() { std::cout << "Destruct " << val << "\n"; }
int val;
};

int main() {
{
sharedptr p1(new Test(10)); std::cout << "use count: " << p1.usecount() << "\n"; // 1

    {
        shared_ptr<Test> p2 = p1;
        std::cout << "use count: " << p1.use_count() << "\n"; // 2
    } // p2析构,引用减1

    std::cout << "use count: " << p1.use_count() << "\n"; // 1
} // p1析构,对象被删除
return 0;

}

输出将清晰展示对象的构造与析构时机,验证引用计数机制的正确性。

总结来说,手动实现shared_ptr不仅是技术练习,更是对C++资源管理哲学的一次深入实践。它让我们意识到:真正的智能不在语法糖,而在对生命周期的精确控制。

资源管理手动实现智能指针C++RAII引用计数shared_ptr
朗读
赞(0)
版权属于:

至尊技术网

本文链接:

https://www.zzwws.cn/archives/39190/(转载时请注明本文出处及文章链接)

评论 (0)