凌云的博客

行胜于言

漫谈 C++ 智能指针 04

分类:c++| 发布时间:2015-10-08 07:48:00


转移所有权

如何将一个智能指针对普通指针的所有权转移给另一个智能指针呢? 你可能首先想到:

bool transfer_ownership()
{
    smart_ptr<int> int_p(new int(3));
    if (!int_p)
        return false;

    smart_ptr<int> int_p2(int_p.release());
    // do some thing
    return true;
}

以上例子是没问题的,但是繁琐了点。 通过实现拷贝构造函数以及重载 operator= 可以更方便的转移所有权。

template<typename T>
class smart_ptr
{
public:
    explicit smart_ptr(T *p = 0): p_(p) {}
    smart_ptr(smart_ptr<T> &rhs): p_(rhs.release()) {}
    ~smart_ptr() {
        clean();
    }

    void reset(T *p) {
        if (p_ == p)
            return;

        clean();
        p_ = p;
    }

    T* get() {
        return p_;
    }

    T* release() {
        T* tmp = p_;
        p_ = 0;
        return tmp;
    }

    smart_ptr<T>& operator= (smart_ptr<T> &rhs) {
        if (this != &rhs) {
            this->reset(rhs.release());
        }

        return *this;
    }

    bool operator! () const {
        return !p_;
    }

    T& operator* () const {
        return *p_;
    }

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

    void clean() {
        if (p_) {
            delete p_;
            p_ = 0;
        }
    }
private:
    T *p_;
};

bool transfer_ownership()
{
    smart_ptr<int> int_p(new int(3));
    if (!int_p)
        return false;

    smart_ptr<int> int_p2(int_p);
    // or:
    // smart_ptr<int> int_p2;
    // int_p2 = int_p;
    // do some thing
    return true;
}

不能在 STL 容器中保存 auto_ptr

到目前为止,我们实现的 smart_ptr 的行为其实跟 auto_ptr 是基本一样的, 因此虽然本节针对的是 auto_ptr 但是同时适用于我们实现的 smart_ptr 。

在 STL 容器中保存 auto_ptr 是不被允许的。 STL 容器中的元素必须是可拷贝以及可赋值的,同时赋值前后的两个元素必须是逻辑独立的。

auto_ptr 不能用于容器的原因是:

void some_func()
{
    auto_ptr<int> p1(new int(3));
    auto_ptr<int> p2;
    p2 = p1;
}

在执行 p2 = p1 之后,p1.get() 为 NULL 也就是说赋值操作会影响到右值。 不满足赋值前后的两个元素必须是逻辑独立的条件。