• 智能指针——学习与应用


    //TO DO

    //
    //  main.cpp
    //  learn_smart_point
    //
    //  Created by New_Life on 2017/8/19.
    //  Copyright © 2017年 chenhuan001. All rights reserved.
    //
    
    #include <iostream>
    #include <vector>
    #include <memory>//the head file of smart point
    
    class TestBase {
    public:
        TestBase() {
            std::cout << "TestBase construct" << std::endl;
        }
    
        ~TestBase() {
            std::cout << "TestBase destroy" << std::endl;
        }
        
        void print_info() {
            std::cout << "TestBase print_info : " << info.c_str() << std::endl;
        }
        
        void set_info(std::string str) {
            info = str;
        }
        
        std::string info;
    };
    
    class TestEqual : public TestBase {
    public:
        TestEqual() {}
        ~TestEqual() {}
        TestEqual& operator = (int a) {
            std::cout << "in operatr = with int" << std::endl;
            return *this;
        }
        
        void operator = (bool a) {
            std::cout << "in operatr = with return void" << std::endl;
            //return *this;
            return ;
        }
    };
    
    class DebugInfo {
    public:
        DebugInfo(const char* info) {
            _info = info;
            std::cout << "------in " << _info.c_str() << "------" << std::endl;
        }
        
        ~DebugInfo() {
            std::cout << "------out " << _info.c_str() << "------" << std::endl;
        }
        
    private:
        std::string _info;
    };
    
    void test_equal() {
        DebugInfo debug_auto_ptr("test_equal");
        TestEqual test_equal;
        test_equal = 1;
        test_equal = true;
        TestEqual test_equal1;
        //test_equal1 = test_equal = false;//whill compile fail
        test_equal1 = test_equal;//默认赋值函数还是存在的
    }
    
    void test_auto_ptr() {
        DebugInfo debug_auto_ptr("test_auto_ptr");
        
        std::auto_ptr<TestBase> base(new TestBase());//封装了下。然后呢
    }
    
    
    int main(int argc, const char * argv[]) {
        //test_equal();
        test_auto_ptr();
        return 0;
    }

    1. std::auto_ptr源码分析

    template <class _Tp> class auto_ptr {
    private:
      _Tp* _M_ptr;
    
    public:
      typedef _Tp element_type; //在类内部typedef
    
      explicit auto_ptr(_Tp* __p = 0) __STL_NOTHROW : _M_ptr(__p) {} //use default argument and nothrow
      auto_ptr(auto_ptr& __a) __STL_NOTHROW : _M_ptr(__a.release()) {} //哇 拷贝构造函数里面,直接把之前的release掉了。
    
      auto_ptr& operator=(auto_ptr& __a) __STL_NOTHROW { //赋值函数也是如此。
        if (&__a != this) {
          delete _M_ptr;//直接把原来的delete
          _M_ptr = __a.release();
        }
        return *this;
      }
    
      ~auto_ptr() __STL_NOTHROW { delete _M_ptr; }
    
      _Tp& operator*() const __STL_NOTHROW {
        return *_M_ptr;
      }
      _Tp* operator->() const __STL_NOTHROW {//神奇的用法。
        return _M_ptr;
      }
      _Tp* get() const __STL_NOTHROW {
        return _M_ptr;
      }
      _Tp* release() __STL_NOTHROW {
        _Tp* __tmp = _M_ptr;
        _M_ptr = 0;
        return __tmp;
      }
      void reset(_Tp* __p = 0) __STL_NOTHROW {
        if (__p != _M_ptr) {
          delete _M_ptr;
          _M_ptr = __p;
        }
      }
    #endif /* auto ptr conversions && member templates */
    };

    上述源码很清晰的说明了auto_ptr的原理。

    auto_ptr是在普通的指针上封装了一层,用于管理指针。

    构造时传入一个指针,析构是将这个指针delete。

    在进行赋值,或者函数参数传递的过程中。会立即把自身保存的指针release掉。

    而release是把当前类保存的指针传出去,然后清空。

    所以使用auto_ptr会有以下几个问题:

    1. 直接调用release后,因为realse本身不会释放保存的指针内存,所以会造成内存泄露。

    2. 唯一传递性,传递给其他auto_ptr对象,当前的对象就不在拥有对该指针的控制权。

    2. boost::scoped_ptr源码分析

    template<class T> class scoped_ptr // noncopyable
    {
    private:
    
        T * px;
    
        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:
    
        typedef T element_type;
    
        explicit scoped_ptr( T * p = 0 ) BOOST_SP_NOEXCEPT : px( p ) // never throws
        {
    #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
            boost::sp_scalar_constructor_hook( px );
    #endif
        }
    
    #ifndef BOOST_NO_AUTO_PTR
    
        explicit scoped_ptr( std::auto_ptr<T> p ) BOOST_NOEXCEPT : px( p.release() )
        {
    #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
            boost::sp_scalar_constructor_hook( px );
    #endif
        }
    
    #endif
    
        ~scoped_ptr() // never throws
        {
    #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
            boost::sp_scalar_destructor_hook( px );
    #endif
            boost::checked_delete( px );
        }
    
        void reset(T * p = 0) // never throws
        {
            BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
            this_type(p).swap(*this);
        }
    
        T & operator*() const // never throws
        {
            BOOST_ASSERT( px != 0 );
            return *px;
        }
    
        T * operator->() const // never throws
        {
            BOOST_ASSERT( px != 0 );
            return px;
        }
    
        T * get() const BOOST_NOEXCEPT
        {
            return px;
        }
    
    // implicit conversion to "bool"
    #include <boost/smart_ptr/detail/operator_bool.hpp>
    
        void swap(scoped_ptr & b) BOOST_NOEXCEPT
        {
            T * tmp = b.px;
            b.px = px;
            px = tmp;
        }
    };

    相对于std::auto_ptr

    boost::scoped_ptr将拷贝构造函数与赋值重载函数设为私有的,也就禁止了拷贝的情况。也就是不会有std::auto_ptr中的问题2.

    因为没有了拷贝的情况,所以boost::scoped_ptr不带有release,所以也不会有std::auto_ptr中的问题1.

    但是scoped_ptr的用法就很局限了,只能在作用范围内使用。不允许交换控制权。

  • 相关阅读:
    ASP.NET MVC 1.0 + spring.net 1.2.0.20288 + NHibernate 2.0.1.4000整合笔记(一)——准备工作
    OpenWRT 编译过程
    XNA 3D模型入门讲解(一)
    Windows Phone7 中实现主从视图
    MVVM之ViewModel
    XNA 三维入门讲解
    WF 4.0 之持久化操作二:Xml方式的存储
    Nhibernate下使用Oracle提示 “Could not create the driver from NHibernate.Driver.OracleDataClientDriver”
    Win8 :修改默认的初始屏幕背景
    Javascript中单引号和双引号引发的悲剧
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/7396112.html
Copyright © 2020-2023  润新知