c++11之shared_ptr的使用记录

环境:vs 2013、win7
作用:
利用引用计数的方式,进而避免堆内存出现意外释放,或者内存泄漏这些危险。
使用方式:
1 std::shared_ptr<Type> 对Type类型,记录其使用数、并可以通过访问指针的方式,直接访问Type  中内容,再在使用数为0时,将对应的Type类型内存释放。
//std::shared_ptr<TestShared> testSharedMake = std::make_shared<TestShared>();
std::shared_ptr<TestShared> testSharedMake0 = testSharedMake;
如上述,当出现对应的赋值语句时,都将导致使用计数增加,(如果原来有引用数,则原来的引用数将减少),当该std::shared_ptr变量被释放(比如离开作用域被回收,或者赋值为nullptr),引用会被减少。
 
2 如何对Type类型指针,构建std::shared_ptr
(1)std::make_shared<TestShared>() ,推荐使用。如果需要调用其它构造函数形式,可以类似调用std::make_shared<TestShared>(x, y..)
(2)std::shared_ptr<TestShared>(new TestShared()); 不推荐使用
很多帖子都书写并贴上数据阐述了:make_shared可以把new控制为一次,所以效率更高。另外就是书写更加一致,毕竟没有delete了,如果还是手动书写new,会很容易让码农们觉得错漏了什么。
//make_shared:构造代码
    // TEMPLATE FUNCTION make_shared
template<class _Ty,
    class... _Types> inline
        shared_ptr<_Ty> make_shared(_Types&&... _Args)
    {    // make a shared_ptr
    _Ref_count_obj<_Ty> *_Rx =
        new _Ref_count_obj<_Ty>(_STD forward<_Types>(_Args)...);

    shared_ptr<_Ty> _Ret;
    _Ret._Resetp0(_Rx->_Getptr(), _Rx);
    return (_Ret);
    }
    template<class... _Types>
        _Ref_count_obj(_Types&&... _Args)
        : _Ref_count_base()
        {    // construct from argument list
        ::new ((void *)&_Storage) _Ty(_STD forward<_Types>(_Args)...);
        }
//std::shared_ptr<TestShared>(new TestShared()) 代码:
    template<class _Ux>
        explicit shared_ptr(_Ux *_Px)
        {    // construct shared_ptr object that owns _Px
        _Resetp(_Px);
        }

    template<class _Ux>
        void _Resetp(_Ux *_Px)
        {    // release, take ownership of _Px
        _TRY_BEGIN    // allocate control block and reset
        _Resetp0(_Px, new _Ref_count<_Ux>(_Px));
        _CATCH_ALL    // allocation failed, delete resource
        delete _Px;
        _RERAISE;
        _CATCH_END
        }
 
3 注意事项,除了上面一项将的构建shared_ptr变量,其它时候,千万不要想当然的用Type*转换为shared_ptr。因为如此是会重新构建一项新的独立的使用计数,如此将导致引用计数最终递减为0时,将会触发多于一次对同一块内存的释放。如下述,是不允许的。(在后面的sample给出代码中,可以把相关注释掉的代码打开,即可以看到出现问题。)
std::shared_ptr<TestShared> testShared = std::shared_ptr<TestShared>(value); //error
 
4 如果需要从this指针中转换得到std::shared_ptr,此时需要将管理的类型继承于:enable_shared_from_this,并使用由其继承得来的shared_from_this(),记得得到期望的shared_ptr数值。如下:
class TestShared : public std::enable_shared_from_this<TestShared>
enable_shared_from_this:集成该类,主要是可以在构建时,记录一个weak_ptr,并在需要时,传送出去,并生成shared_ptr
template<class _Ty1,
    class _Ty2>
    inline void _Do_enable(
        _Ty1 *_Ptr,
        enable_shared_from_this<_Ty2> *_Es,
        _Ref_count_base *_Refptr)
    {    // reset internal weak pointer
    _Es->_Wptr._Resetw(_Ptr, _Refptr);
    }

 

//sample 代码:
#ifndef _TEST_SHARED_H_
#define _TEST_SHARED_H_

#include <memory>
class  TestShared : public std::enable_shared_from_this<TestShared>
{
public:
     TestShared();
    ~ TestShared();

    std::shared_ptr<TestShared> GetSharedObject();
private:
};

 TestShared:: TestShared()
{
}

 TestShared::~ TestShared()
{
}

 std::shared_ptr<TestShared>  TestShared::GetSharedObject()
 {
     return shared_from_this();
 }

#endif //_TEST_SHARED_H_

    std::shared_ptr<TestShared> testSharedMake = std::make_shared<TestShared>();
    std::cout << "testSharedMake \t\t"<<" shared_count: " << testSharedMake.use_count() << std::endl;
    std::shared_ptr<TestShared> testSharedMake0 = testSharedMake;
    std::cout << "testSharedMake \t\t"<< " shared_count: " << testSharedMake.use_count() << std::endl;
    std::cout << "testSharedMake0 \t\t"<< " shared_count: " << testSharedMake0.use_count() << std::endl;

    TestShared* value = testSharedMake.get();

    //std::shared_ptr<TestShared> testShared = std::shared_ptr<TestShared>(value);
    //std::cout << "testShared \t\t" << " shared_count: " << testShared.use_count() << std::endl;
    //std::cout << "testSharedMake \t\t" << " shared_count: " << testSharedMake.use_count() << std::endl;

    std::shared_ptr<TestShared> testSharedFromThis = value->GetSharedObject();
    //std::cout << "testShared \t\t" << " shared_count: " << testShared.use_count() << std::endl;
    std::cout << "testSharedMake \t\t" << " shared_count: " << testSharedMake.use_count() << std::endl;
    std::cout << "testSharedFromThis \t\t" << " shared_count: " << testSharedFromThis.use_count() << std::endl;

    std::shared_ptr<TestShared> testSharedFromThis0 = testSharedMake->GetSharedObject();
    //std::cout << "testShared \t\t\t" << " shared_count: " << testShared.use_count() << std::endl;
    std::cout << "testSharedMake \t\t" << " shared_count: " << testSharedMake.use_count() << std::endl;
    std::cout << "testSharedMake0 \t\t" << " shared_count: " << testSharedMake0.use_count() << std::endl;
    std::cout << "testSharedFromThis0 \t\t" << " shared_count: " << testSharedFromThis0.use_count() << std::endl;

附上上述运行结果:

testSharedMake shared_count: 1
testSharedMake shared_count: 2
testSharedMake0 shared_count: 2
testSharedMake shared_count: 3
testSharedFromThis shared_count: 3
testSharedMake shared_count: 4
testSharedMake0 shared_count: 4
testSharedFromThis0 shared_count: 4

遗留问题:
1 make_shared:如何保障只调用一次new
2 make_shared:如何保证可以调用多种形式的构造函数?
posted @ 2016-10-11 21:02  lanyuan  阅读(3869)  评论(0编辑  收藏  举报