C++ Boost shared_ptr:如何使用自定义删除器和分配器

C++ Boost shared_ptr:如何使用自定义删除器和分配器,c++,boost,smart-pointers,C++,Boost,Smart Pointers,自由函数分配\u共享可与任何符合标准的分配器一起使用。但是shared_ptr的构造函数和重置方法呢 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); 模板共享(Y*p,D,A); 模板无效重置(Y*p,D,A); 手册规定,D应提供一个用于删除指针的呼叫操作符

自由函数分配\u共享可与任何符合标准的分配器一起使用。但是shared_ptr的构造函数和重置方法呢

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);
模板共享(Y*p,D,A);
模板无效重置(Y*p,D,A);
手册规定,D应提供一个用于删除指针的呼叫操作符,a必须是符合标准的分配器。如果是,为什么需要DA不能同时进行分配和去分配吗您不认为为每个自定义分配器提供删除器的要求使得上述方法几乎毫无用处吗?当我使用自定义分配器时,我选择allocate\U shared。如何知道释放自定义分配器分配的内存的正确方法


编辑:在使用逐字分配器和删除器进行一些实验后,我发现分配器传递给共享\u ptr的构造函数和工厂函数allocate\u shared仅用于分配共享\u ptr的内部结构allocate\u shared从不使用传递的分配器分配共享对象。我认为boost手册可以更明确地解释如何使用分配器。

分配器旨在用于分配和取消分配内部
共享的\u ptr
详细信息,而不是对象

也就是说,虽然deleter让我们完全控制共享对象(因为我们控制它的获取和释放方式),但allocator参数让我们控制对象共享性质的内部细节

如果您看一下,在分配器建议的末尾,他们注意到Boost已经实现了该功能,并链接到一个示例来演示它的使用

下面就是这个例子,逐字记录:

#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();
}
#包括
//共享\u ptr\u alloc2\u test.cpp
//
//版权所有(c)2005彼得·迪莫夫
//
//根据Boost软件许可证1.0版发布。(见
//随附文件LICENSE_1_0.txt或副本
// http://www.boost.org/LICENSE_1_0.txt)
#包括
#包括
#包括
#包括
//测试分配器
结构测试分配程序库
{
int-id_2;;
静态int last\u global\u id;
静态整数计数;
显式测试分配器基(int-id):id(id)
{
}
};
int test_分配器_base::last_global_id_u=0;
int test_分配器_base::count_u=0;
模板类测试分配器:公共测试分配器库
{
公众:
typedef T*指针;
typedef T const*const_指针;
typedef T&reference;
类型定义T常数和常数参考;
类型定义T值_类型;
typedef std::size\u t size\u type;
typedef std::ptrdiff_t difference_type;
私人:
静态T*最后一个指针;
静态标准::最后的大小;
静态int last\u id;
公众:
模板结构重新绑定
{
typedef测试分配器其他;
};
指针地址(参考r)常数
{
返回&r;
}
常量指针地址(常量引用)常量
{
返回&s;
}
显式测试分配器(int id=0):测试分配器(id)
{
}
模板测试分配器(测试分配器常量&r):测试分配器基数(r)
{
}
模板测试分配器和运算符=(测试分配器常量和r)
{
test_分配器_base::operator=(r);
归还*这个;
}
无效解除分配(指针p,大小\类型n)
{
升压试验(p==最后一个指针);
升压试验(n==最后一次试验);
升压试验(id=最后一个id);
--伯爵;
::运算符删除(p);
}
指针分配(大小\类型n,无效常量*)
{
T*p=static_cast(::操作符new(n*sizeof(T));
最后一个指针=p;
最后的n=n;
最后一个\u id\u=id\u;
最后一个\u全局\u id=id;
++伯爵;
返回p;
}
无效构造(指针p、T常量和T)
{
新(p)T(T);
}
无效销毁(指针p)
{
p->~T();
}
大小\类型最大大小()常量
{
返回大小\u类型(-1)/sizeof(T);
}
};
模板T*测试分配器::最后一个指针=0;
模板std::size\u t test\u分配器::last\u n\u=0;
template int test\u分配器::last\u id\u0;
模板内联布尔运算符==(测试分配器常数&a1,测试分配器常数&a2)
{
返回a1.id==a2.id;
}
模板内联布尔运算符=(测试分配器常数和a1,测试分配器常数和a2)
{
返回a1.id!=a2.id;
}
模板类测试分配器:公共测试分配器库
{
公众:
typedef void*指针;
typedef void const*const_指针;
typedef void value_type;
模板结构重新绑定
{
typedef测试分配器其他;
};
显式测试分配器(int id=0):测试分配器(id)
{
}
模板测试分配器(测试分配器常量&r):测试分配器基数(r)
{
}
模板测试分配器和运算符=(测试分配器常量和r)
{
test_分配器_base::operator=(r);
归还*这个;
}
};
//
结构X
{
静态int实例;
X()
{
++实例;
}
~X()
{
--实例;
}
私人:
X(X常数&);
X&运算符=(X常数&);
};
intx::instances=0;
int main()
{
BOOST_测试(X::instances==0);
boost::shared_ptr pv(新X,boost::checked_deleter(),std::allocator());
BOOST_测试(X::instances==1);
重置(新X,boost::checked_deleter(),test_分配器(42));
BOOST_测试(X::instances==1);
BOOST_TEST(TEST_分配器_base::last_global_id_==42);
BOOST_测试(测试分配器_base::count_u>0);
pv.reset();
BOOST_测试(X::instances==0);
BOOST_TEST(TEST_分配器_base::count_==0);
重置(新X,boost::checked_deleter(),test_分配器(43));
BOOST_测试(X::instances==1);
嘘声