【C++】不带引用计数的智能指针

不带引用计数的指针的浅拷贝会导致重复析构同一资源。

template<typename T>
class CSmartPtr{
public:
    CSmartPtr(T* ptr = nullptr)
        :mptr(ptr){}
    ~CSmartPtr(){ delete mptr;}

    // CSmartPtr(const CSmartPtr<T> &src){
    //     mptr = new T(*(src.mptr));
    // }


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

private:
    T* mptr;
};

int main(){

    /*
     * 不带引用计数的智能指针
     */
    CSmartPtr<int> p1(new int);
    CSmartPtr<int> p2(p1); // 浅拷贝,重复析构统一资源
}

不带引用计数的智能指针是如何解决浅拷贝问题的?

auto_ptr

作用简单,退出作用域析构时直接释放其内裸指针指向的内存地址。只让最后一个拷贝的指针指向资源区。转移对象的持有权。

#include <iostream>
#include <memory>
using namespace std;


template<typename T>
class CSmartPtr{
public:
    CSmartPtr(T* ptr = nullptr)
        :mptr(ptr){}
    ~CSmartPtr(){ delete mptr;}

    // CSmartPtr(const CSmartPtr<T> &src){
    //     mptr = new T(*(src.mptr));
    // }

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

private:
    T* mptr;
};

int main(){

    /*
     * 不带引用计数的智能指针
     * auto_ptr: C++库里面
     * C++11
     * scoped_ptr
     * unique_ptr
     */


    /*
     * 怎么解决浅拷贝问题!!!
     */

    // CSmartPtr<int> p1(new int);
    // CSmartPtr<int> p2(p1); // 浅拷贝,重复析构统一资源

    auto_ptr<int> ptr1(new int);
    auto_ptr<int> ptr2(ptr1); // 将被拷贝对象的资源移走置空

    *ptr2 = 20;

    cout << *ptr2 << endl;
}

浅拷贝逻辑

转移对象的持有权。只让最后一个拷贝的指针指向资源区,之前的指针置空。

auto_ptr<int> ptr2(ptr1);
	ptr1.release(); // 拷贝构造

不推荐使用auto_ptr

vector<auto_ptr<int>> vec1;
vec2(vec1); // 导致容器vec1中的智能指针全部置空

建议只在简单管理内存时使用

scoped_ptr

直接禁止拷贝,单独一对一管理一块内存

scoped_ptr(const scoped_ptr<T>&) = delete;
scoped_ptr<T>& operator=(const scoped_ptr<T>&) = delete;

unique_ptr

类似scoped_ptr,删除了直接的拷贝构造

unique_ptr(const unique_ptr<T>&) = delete;
unique_ptr<T>& operator=(const unique_ptr<T>&) = delete;

但是提供了与auto_ptr类似的右值的拷贝构造和赋值运算重载

unique_ptr(const unique_ptr<T> &&src)
unique_ptr<T>& operator=(unique_ptr<T> &&src)
template<typename T>
unique_ptr<T> getSmartPtr(){
	unique_ptr<T> ptr(new T());
	return ptr;
}

// 函数返回的对象可以作为右值赋值给ptr
unique_ptr<int> ptr = getSmartPtr<int>();

几乎与auto_ptr相同,但其资源转移过程需要显式move,减少语义上的模糊性,推荐使用。

posted @ 2025-05-01 17:00  丘狸尾  阅读(20)  评论(0)    收藏  举报