漫谈 C++ 智能指针 02

分类:c++| 发布时间:2015-09-18 23:10:00
原文: http://cs-cjl.com/2015/09_18_cpp_smart_pointer_02


更通用的智能指针

在上一节中,我们给出了一个智能指针的简单实现,但是这个实现有一个严重的问题,
它只能保存 some_type 类型的指针。
如何实现一个更加通用的智能指针呢?
通过使用模板可以简单地实现这一目的:

template<typename T>
class smart_ptr
{
public:
    explicit smart_ptr(T *p): p_(p) {}
    ~smart_ptr() {
        clean();
    }

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

        clean();
        p_ = p;
    }

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

bool some_func()
{
    smart_ptr<int> int_p;
    smart_ptr<some_type> some_type_p;
    {
        some_type *tmp = new some_type();
        if (!tmp)
            return false;

        some_type_p.reset(tmp);
    }

    {
        int *tmp = new int(3);
        if (!tmp)
            return false;

        int_p.reset(tmp);
    }
    // do something
    if (failed) {
        // Ok, it will delete auto
        return false;
    }

    return true;
}

可以看到,使用了模板之后 smart_ptr 可以保存任意类型的指针,
所需要做的改变只是在尖括号内给出指针的类型(如 auto_ptr 等标准实现一样)。

获取普通(裸)指针

在上面的例子中,通过我们实现的智能指针可以确保在函数结束时释放内存。
但上面的实现缺少一个非常重要的功能,先来看一个例子:

int *make_int()
{
    int *tmp = new int(3);
    if (!tmp)
        return 0;

    if (failed)
        return 0;

    return tmp;
}

bool some_func()
{
    smart_ptr<int> int_p(make_int());
    if (int_p is null)
        return false;

    // set int to 4
    // Oops: not way to do it
    return true;
}

在上面的例子中,我们想要将 4 赋给 int_p 指向的值。
却发现没有方法或者 int_p 包含的原始指针,我们需要添加一个方法以返回它的原始指针。

template<typename T>
class smart_ptr
{
public:
    // See other impl above

    T* get() {
        return p_;
    }
private:
    T *p_;
};

// see make_int above
bool some_func()
{
    smart_ptr<int> int_p(make_int());
    if (!int_p.get())
        return false;

    // set int to 4
    (*int_p.get()) = 4;
    return true;
}

我们添加了一个返回原始指针 get() 方法使得可以操作原始指针。
(事实上,在所有的智能指针实现中都会添加这么一个方法。)

放弃所有权

假设我们的函数 some_func 需要将 int_p 拥有的原始指针返回,我们应该怎么做呢?
直接通过 get() 获取原始指针然后返回?

int* some_func()
{
    smart_ptr<int> int_p(make_int());
    if (!int_p.get())
        return 0;

    // set int to 4
    (*int_p.get()) = 4;
    return int_p.get();
}

上述代码会不会有问题呢?
当 some_func 结束时,int_p 的生命周期也结束了,这是他的析构函数会 delete 掉它本身
所拥有的原始指针。因此,some_func 会返回一个无效的指针。

我们需要一个函数在返回原始指针的同时,放弃对原始指针的所有权。
这个函数通常被命名为 release() 。

template<typename T>
class smart_ptr
{
public:
    // See other impl above

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

int* some_func()
{
    smart_ptr<int> int_p(make_int());
    if (!int_p.get())
        return 0;

    // set int to 4
    (*int_p.get()) = 4;
    return int_p.release();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值