CPP

智能指针及其作用

2018-03-29  本文已影响404人  顽强的猫尾草

一、引入背景

使用 C++ 的指针可以动态开辟存储空间,但若在使用完毕后忘记释放(或在释放之前,程序 throw 出错误,导致没有释放),导致该内存单元一直被占据直到程序结束,即发生了所谓的内存泄漏
【注】内存泄漏是指堆内存的泄漏。堆,就是那些由 new 分配的内存块。
  因此智能指针的作用就是为了保证使用堆上对象的时候,对象一定会被释放,但只能释放一次,并且释放后指向该对象的指针应该马上归 0

二、C++11 以前的智能指针

auto_ptr,指向一个动态分配的对象指针,它的析构函数用于删除所指对象的空间,以此达到对对象生存期的控制。
  已被弃用,原因是:

三、C++11 标准的智能指针

加入了 unique_ptr、shared_ptr 和 weak_ptr。

  1. unique_ptr,等于 boost 库中的 scoped_ptr,正如其名字所述,scoped_ptr 所指向的对象在作用域之外会自动得到析构
    【注】boost 库是 Boost 社区在 C++11 之前嫌弃标准更新太慢,而自发组织开发、维护的一个扩展库。通过包含头文件 ”boost/scoped_ptr.hpp” 来引入。
    简单定义:
namespace boost
{
    // scoped_ptr 是 non-copyable 的
    // 也就是说你不能去尝试复制一个 scoped_ptr 的内容到另外一个 scoped_ptr 中
    // 这也是为了防止错误地多次析构同一个指针所指向的对象
    template<typename T> class scoped_ptr : noncopyable

    {
    private:

        T *px;
                                             
        // scoped_ptr 不能通过其他 scoped_ptr 共享控制权
        // 因此在 scoped_ptr 类的内部将拷贝构造函数和 = 运算符重载定义为 private
        scoped_ptr(scoped_ptr const &);
        scoped_ptr &operator=(scoped_ptr const &);

        typedef scoped_ptr<T> this_type;

        void operator==( scoped_ptr const & ) const;
        void operator!=( scoped_ptr const & ) const;

    public:

        // 构造函数显示定义,不能通过隐式转换(赋值操作符 =)构造
        explicit scoped_ptr(T *p = 0);
        ~scoped_ptr();

        explicit scoped_ptr( std::auto_ptr<T> p ): px( p.release() );
        // 在 scoped_ptr 离开作用域之前也可以显式销毁它们所管理的对象,调用它的 reset 方法即可
        void reset(T *p = 0);

        T &operator*() const;
        T *operator->() const;
        T *get() const;

        // 虽然 scoped_ptr 不能转移控制权,但是它们可以交换控制权
        void swap(scoped_ptr &b);
    };

    template<typename T>
    void swap(scoped_ptr<T> &a, scoped_ptr<T> &b);
}
  1. shared_ptr,可共享指针对象,可以赋值给 shared_ptr 或 weak_ptr。shared_ptr 中所实现的本质是引用计数,拷贝一个 shared_ptr 将对这个智能指针的引用次数加 1,而当这个智能指针的引用次数降低到 0 的时候,该对象自动被析构。
    代码部分与 scoped_ptr 类似,只是支持拷贝、赋值和==、!=。

  2. weak_ptr
    weak_ptr 和 shared_ptr 的最大区别在于 weak_ptr 在指向一个对象的时候不会增加其引用计数,因此你可以用 weak_ptr 去指向一个对象并且在 weak_ptr 仍然指向这个对象的时候析构它,此时你再访问 weak_ptr 的时候,weak_ptr 返回的会是一个空的 shared_ptr。
    常被用来解决环状引用问题,告诉 C++ 环上哪一个引用是最弱的,因此在一个环上把原来的某一个 shared_ptr 改成 weak_ptr 就可以了。

【注】以上 std 标准库的智能指针都可以通过包含头文件 <memory> 来引入。

上一篇 下一篇

猜你喜欢

热点阅读