面试问题-实现cpp智能指针

memetao 于 2025-02-09 发布

UniquePtr

第一步

private: T* ptr_; };

### 第二步

* 禁止拷贝和赋值运算符
* 支持移动构造
* 支持移动赋值运算发
```c++
    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;

    unique_ptr(unique_ptr&& other) noexcept : ptr_(other.ptr_) {
        other.ptr_ = nullptr;
    }

    unique_ptr& operator=(unique_ptr&& other) noexcept {
        if (ptr_) {
            delete ptr_;
        }
        ptr_ = other.ptr_;
        other.ptr = nullptr;
        return *this;
    }

出现问题了: 如果other==this? 所以需要判断一下是否就是自己

if (this != &other) {
    delete ptr;
    ptr = other.ptr;
    other.ptr = nullptr;
}

第三步

T* operator->() const { return ptr_; }
T& operator*() const { return *ptr_; }

shared_ptr

template <typename T> class DefaultDeletor {
public:
    void operator()(const T* ptr) {
        if (ptr) {
            delete ptr;
        }
    }
};

template <typename T, typename Deleter = DefaultDeletor<T>> class shared_ptr {
public:
    shared_ptr(T* ptr = nullptr)
        : ptr_(ptr) {
        ref_ = new int64_t(1);
    }

    ~shared_ptr() { release(); }

    shared_ptr(const shared_ptr& other)
        : ptr_(other.ptr_)
        , ref_(ohter.ref_) {
        (*ref_)++;
    }

    shared_ptr& operator=(const shared_ptr& other) {
        if (this == ohter) {
            return;
        }
        ref_ = other.ref_;
        ptr_ = other.ptr_;
        (*ref_)++;
    }

    shared_ptr(shared_ptr&& other)
        : ptr_(other.ptr_) {
        ref_ = other.ref_;
        other.ptr_ = nullptr;
        other.ref_ = nullptr;
    }

    void reset(T* ptr) {
        release();
        ref_ = new int64_t(1);
        ptr_ = ptr;
    }

    void swap(shared_ptr& other) {
        std::swap(ptr, other.ptr);
        std::swap(refCount, other.refCount);
    }

    T* get() const { return ptr_; }
    T& operator*() const { return *ptr_; }
    T* operator->() const { return ptr_; }
    int64_t use_count() const { return *ref_; }

private:
    void release() {
        --(*ref_);
        if (ref_ == 0 && ptr_) {
            deleter(ptr_);
            delete ref_;
            ptr_ = nullptr;
            ref_ = nullptr;
        }
    }

private:
    T* ptr_ = nullptr;
    int64_t* ref_ = 0;
    Deleter deleter;
};

weak_ptr

第一步

template <typename T>
class SharedPtr;

template <typename T>
class WeakPtr {
private:
    T* ptr;
    std::atomic<unsigned>* refCount;   // 强引用计数
    std::atomic<unsigned>* weakCount;  // 弱引用计数

public:
    // 默认构造
    WeakPtr() : ptr(nullptr), refCount(nullptr), weakCount(nullptr) {}

    // 允许从 SharedPtr 构造
    WeakPtr(const SharedPtr<T>& sp) noexcept
        : ptr(sp.ptr), refCount(sp.refCount), weakCount(sp.weakCount) {
        if (weakCount) {
            ++(*weakCount);
        }
    }
    WeakPtr(const WeakPtr& other) noexcept
        : ptr(other.ptr), refCount(other.refCount), weakCount(other.weakCount) {
        if (weakCount) {
            ++(*weakCount);
        }
    }
    WeakPtr& operator=(const WeakPtr& other) noexcept {
        if (this != &other) {
            release();
            ptr = other.ptr;
            refCount = other.refCount;
            weakCount = other.weakCount;
            if (weakCount) {
                ++(*weakCount);
            }
        }
        return *this;
    }
    void release() {
        if (weakCount && --(*weakCount) == 0) {
            delete weakCount;
        }
    }

    ~WeakPtr() {
        release();
    }

    bool expired() const {
        return !refCount || *refCount == 0;
    }

    SharedPtr<T> lock() const {
        return (expired()) ? SharedPtr<T>() : SharedPtr<T>(*this);
    }
};

第二步

修改shared_ptr以支持weak_ptr

    T* ptr;
    std::atomic<unsigned>* refCount;   // 强引用计数
    std::atomic<unsigned>* weakCount;  // 弱引用计数
 // 从 WeakPtr 构造
SharedPtr(const WeakPtr<T>& wp) noexcept
    : ptr(wp.ptr), refCount(wp.refCount), weakCount(wp.weakCount) {
    if (refCount && *refCount > 0) {
        ++(*refCount);
    } else {
        ptr = nullptr;  // 资源已释放
    }
}

shared_from_this

关键的关键,需要在shared_ptr的构造函数中调用set_ref:

template <typename T>
class enable_shared_from_this {
protected:
    // 构造函数将 `shared_ptr` 管理的引用计数保存下来
    enable_shared_from_this() = default;
    ~enable_shared_from_this() = default;

public:
    // 获取一个指向当前对象的 shared_ptr
    std::shared_ptr<T> shared_from_this() {
        // 先验证是否已经由 shared_ptr 管理
        assert(refCount != nullptr && *refCount > 0);
        return std::shared_ptr<T>(this);  // 返回指向当前对象的 shared_ptr
    }

    // 共享对象时创建一个强引用计数
    void set_refCount(std::atomic<unsigned>* ref) {
        refCount = ref;
    }

private:
    std::atomic<unsigned>* refCount = nullptr;  // 用来跟踪引用计数
};
explicit SharedPtr(T* p = nullptr)
    : ptr(p), refCount(new std::atomic<unsigned>(1)) {
    if (ptr) {
        set_refCount(ptr, refCount);  // 将控制块传给对象
    }
}

那么,对于没有继承enable_shared_form_this的类怎么办呢?实现两套:

template<typename T>
void set_refCount(shared_ptr<T> t, enable_shared_from_this<T>* e)
{
    e->set_refCount(t);
}

void set_refCount(...)
{
    //do nothing
}