如何在 C++11 中将自定义分配器传递给 std::basic_ostringstream?

How to pass custom allocator to std::basic_ostringstream in C++11?

我想使用自定义分配器从空闲列表中为 std::basic_ostringstream 分配内存。这是我要使用的自定义分配器:

template <class Tp>

    struct NAlloc {
        typedef Tp value_type;
        typedef value_type* pointer;
        typedef const value_type* const_pointer;
        typedef value_type& reference;
        typedef const value_type& const_reference;
        typedef std::size_t size_type;
        typedef std::ptrdiff_t difference_type;

        NAlloc() = default;
        template <class T> NAlloc(const NAlloc<T>&) {}
        Tp* allocate(std::size_t n) {
            n *= sizeof(Tp);
            memoryPool *memPool = memoryPool::GetInstance(10);//get memory pool instance
            std::cout << "allocating " << n << " bytes\n";
            return static_cast<Tp*>(memPool->allocate(n)); //get memory from pool
        }
        void deallocate(Tp* p, std::size_t n) {
            std::cout << "deallocating " << n*sizeof*p << " bytes\n";
            memoryPool *memPool = memoryPool::GetInstance(10);
            memPool->deallocate(static_cast<void*>(p));//return memory to pool
        }

   template<typename U>
   struct rebind {
    typedef NAlloc<U> other;
   };

然后,我这样使用它:

typedef std::basic_string<char, std::char_traits<char>, NAlloc<char>> OstringStream;

****问题:****

int main()
{
    OstringStream os; //Object creation
    os << " Hello, this is OstreamStream class with memory pool";  //here I am getting error
}

Error: 'OstringStream {aka std::basic_string<char, std::char_traits<char>, NAlloc<char> >}' is not derived from 'std::basic_ostream<_CharT, _Traits>'

您的 OstringStream 类型是 std::basic_string, not of std::basic_ostream 的类型定义。这就是您从 operator<< 收到错误的原因。左边的操作数必须是从 std::basic_ostream 派生的对象,正如错误消息所说的那样。

std::basic_ostream 本身根本不使用分配器。它使用 std::basic_streambuf for all of its I/O. For instance, std::ostringstream uses std::stringbuf,它使用默认的 std::allocator

在 C++11 中,std::basic_ostringstream 有一个可选的 Allocator 模板参数,它向下传递给它的内部 std::basic_stringbuf。所以,你可以这样写你的typedef

typedef std::basic_ostringstream<char, std::char_traits<char>, NAlloc<char>> OstringStream;

int main()
{
    OstringStream os;
    os << " Hello, this is OstringStream with memory pool";
}

在早期的 C++ 版本中,您必须:

  1. 定义 std::basic_stringbuf 的 typedef,它使用自定义分配器而不是默认分配器。

  2. 构造一个标准 std::ostream 对象,该对象使用自定义 stringbuf 类型的实例。

例如:

typedef std::basic_stringbuf<char, std::char_traits<char>, NAlloc<char> > Stringbuf_NAlloc;

class OstringStream : public Stringbuf_NAlloc, public std::ostream
{
public:
    OstringStream() : Stringbuf_NAlloc(std::ios_base::out), std::ostream(this) {}
};

int main()
{
    OstringStream os;
    os << " Hello, this is OstringStream with memory pool";
}

无论哪种情况,都知道 os.str() 方法将不再是 return 标准 std::string,它使用默认分配器。它将 return 一个 std::basic_string 改用您的自定义分配器。这将在尝试将 os.str() 的 return 值分配给标准 std::string 时引起问题,例如:

std::string s = os.str(); // error!

error: conversion from ‘std::__cxx11::basic_ostringstream<char, std::char_traits<char>, NAlloc>::__string_type {aka std::__cxx11::basic_string<char, std::char_traits<char>, NAlloc>}’ to non-scalar type ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ requested

所以请注意这一点。在混合分配器方面,STL 不是很灵活,因此如果您使用自定义分配器,通常必须将其应用到您从 STL 使用的每种类型的数据容器。