升压shared_ptr的:如何使用自定义删除器和分配器 [英] Boost shared_ptr: How to use custom deleters and allocators

查看:738
本文介绍了升压shared_ptr的:如何使用自定义删除器和分配器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自由功能的 allocate_shared 可以与任何符合标准的分配器使用。但是,我们的shared_ptr的构造和复位方法。

Free function allocate_shared can be used with any standard compliant allocator. But what about shared_ptr's constructor and reset method.

template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
template<class Y, class D, class A> void reset(Y * p, D d, A a);

手册说的 D 应提供将用于删除指针和 A 必须是符合标准的分配器的呼叫运营商。如果是这样,为什么 D 需要?不能 A 一举两得分配和delocation? 不要你认为需要提供的删除每一个自定义分配器,使上述方法pretty无用?当我使用自定义的分配,我去的 allocate_shared 。我怎么知道什么是通过自定义分配器分配的内存的正确方法?

The manual says that D should provide a call operator which will be used to delete the pointer and A must be a standard compliant allocator. If so, why D is needed? Can't A do both allocation and delocation? Don't you think that the requirement to provide a deleter for every custom allocator makes the above methods pretty much useless? When I use custom allocators, I go for allocate_shared. How do I know what is the proper way to free memory allocated by a custom allocator?

编辑:一些实验用逐字分配器和删除器我想通了,分配器传递给构造函数后的的shared_ptr 并到工厂功能的 allocate_shared 用于分配的内部结构的的shared_ptr 只。 allocate_shared 从来没有使用过通过分配器分配的共享对象。我认为,升压手动可能解释了分配是如何使用更明确。

After some experimentation with a verbatim allocator and a deleter I figured out that the allocator passed to the constructor of shared_ptr and to the factory function allocate_shared is used to allocate the internal structure of shared_ptr only. allocate_shared never uses the passed allocator to allocate the shared object. I think that the boost manual could have explained how the allocator is used more explicitly.

推荐答案

分配器旨在用于分配和释放的内部的shared_ptr 详细信息,而不是对象

The allocator is intended to be used to allocate and deallocate internal shared_ptr details, not the object.

也就是说,虽然删除器让我们完全控制了我们的共享对象(因为我们控制它是如何获取和释放),分配器参数让我们控制我们对象的共享特性的内部细节。

That is, while the deleter gives us full control over our shared object (because we control how it's acquired and released), the allocator parameter gives us control over the internal details of our object's shared nature.

如果你看一下 N2351 ,在结束分配器建议他们指出,加速实施该功能,并链接到是为了证明其使用的例子。

If you look at N2351, at the end of the allocator proposal they note that Boost has implemented the feature, and link to an example that was made to demonstrate its use.

下面是一个例子,逐字:

Here is that example, verbatim:

#include <boost/config.hpp>

//  shared_ptr_alloc2_test.cpp
//
//  Copyright (c) 2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)


#include <boost/detail/lightweight_test.hpp>
#include <boost/shared_ptr.hpp>
#include <memory>
#include <cstddef>

// test_allocator

struct test_allocator_base
{
    int id_;

    static int last_global_id_;
    static int count_;

    explicit test_allocator_base( int id ): id_( id )
    {
    }
};

int test_allocator_base::last_global_id_ = 0;
int test_allocator_base::count_ = 0;

template<class T> class test_allocator: public test_allocator_base
{
public:

    typedef T * pointer;
    typedef T const * const_pointer;
    typedef T & reference;
    typedef T const & const_reference;
    typedef T value_type;
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;

private:

    static T * last_pointer_;
    static std::size_t last_n_;
    static int last_id_;

public:

    template<class U> struct rebind
    {
        typedef test_allocator<U> other;
    };

    pointer address( reference r ) const
    {
        return &r;
    }

    const_pointer address( const_reference s ) const
    {
        return &s;
    }

    explicit test_allocator( int id = 0 ): test_allocator_base( id )
    {
    }

    template<class U> test_allocator( test_allocator<U> const & r ): test_allocator_base( r )
    {
    }

    template<class U> test_allocator & operator=( test_allocator<U> const & r )
    {
        test_allocator_base::operator=( r );
        return *this;
    }

    void deallocate( pointer p, size_type n )
    {
        BOOST_TEST( p == last_pointer_ );
        BOOST_TEST( n == last_n_ );
        BOOST_TEST( id_ == last_id_ );

        --count_;

        ::operator delete( p );
    }

    pointer allocate( size_type n, void const * )
    {
        T * p = static_cast< T* >( ::operator new( n * sizeof( T ) ) );

        last_pointer_ = p;
        last_n_ = n;
        last_id_ = id_;

        last_global_id_ = id_;
        ++count_;

        return p;
    }

    void construct( pointer p, T const & t )
    {
        new( p ) T( t );
    }

    void destroy( pointer p )
    {
        p->~T();
    }

    size_type max_size() const
    {
        return size_type( -1 ) / sizeof( T );
    }
};

template<class T> T * test_allocator<T>::last_pointer_ = 0;
template<class T> std::size_t test_allocator<T>::last_n_ = 0;
template<class T> int test_allocator<T>::last_id_ = 0;

template<class T, class U> inline bool operator==( test_allocator<T> const & a1, test_allocator<U> const & a2 )
{
    return a1.id_ == a2.id_;
}

template<class T, class U> inline bool operator!=( test_allocator<T> const & a1, test_allocator<U> const & a2 )
{
    return a1.id_ != a2.id_;
}

template<> class test_allocator<void>: public test_allocator_base
{
public:

    typedef void * pointer;
    typedef void const * const_pointer;
    typedef void value_type;

    template<class U> struct rebind
    {
        typedef test_allocator<U> other;
    };

    explicit test_allocator( int id = 0 ): test_allocator_base( id )
    {
    }

    template<class U> test_allocator( test_allocator<U> const & r ): test_allocator_base( r )
    {
    }

    template<class U> test_allocator & operator=( test_allocator<U> const & r )
    {
        test_allocator_base::operator=( r );
        return *this;
    }
};

//

struct X
{
    static int instances;

    X()
    {
        ++instances;
    }

    ~X()
    {
        --instances;
    }

private:

    X( X const & );
    X & operator=( X const & );
};

int X::instances = 0;

int main()
{
    BOOST_TEST( X::instances == 0 );

    boost::shared_ptr<void> pv( new X, boost::checked_deleter<X>(), std::allocator<X>() );

    BOOST_TEST( X::instances == 1 );

    pv.reset( new X, boost::checked_deleter<X>(), test_allocator<float>( 42 ) );

    BOOST_TEST( X::instances == 1 );

    BOOST_TEST( test_allocator_base::last_global_id_ == 42 );
    BOOST_TEST( test_allocator_base::count_ > 0 );

    pv.reset();

    BOOST_TEST( X::instances == 0 );
    BOOST_TEST( test_allocator_base::count_ == 0 );

    pv.reset( new X, boost::checked_deleter<X>(), test_allocator<void>( 43 ) );

    BOOST_TEST( X::instances == 1 );
    BOOST_TEST( test_allocator_base::last_global_id_ == 43 );

    pv.reset( new X, boost::checked_deleter<X>(), std::allocator<void>() );

    BOOST_TEST( X::instances == 1 );

    pv.reset();

    BOOST_TEST( X::instances == 0 );

    return boost::report_errors();
}

这篇关于升压shared_ptr的:如何使用自定义删除器和分配器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆