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

Posted

技术标签:

【中文标题】如何在 C++11 中将自定义分配器传递给 std::basic_ostringstream?【英文标题】:How to pass custom allocator to std::basic_ostringstream in C++11? 【发布时间】:2018-01-23 16:06:23 【问题描述】:

我想使用自定义分配器从空闲列表中为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

错误:'OstringStream aka std::basic_string, NAlloc >' 不是从 'std::basic_ostream<_chart _traits>' 派生的

【问题讨论】:

你有什么问题? 如果我这样做,OstringStream os, os , NAlloc >' 不是从 'std::basic_ostream<_chart _traits>' 派生的 你需要edit问题来显示你的问题(而不是添加评论)。请写一个minimal reproducible example 并将其包含在问题的正文中。谢谢。 如果您需要帮助,您需要实际提出问题。请把它放在问题中而不是评论中。 您是否必须重载 【参考方案1】:

您的OstringStream 类型是std::basic_string 的typedef,而不是std::basic_ostream。这就是为什么您会收到来自operator&lt;&lt; 的错误。左边的操作数必须是从std::basic_ostream 派生的对象,正如错误消息所说的那样。

std::basic_ostream 本身根本不使用分配器。它的所有 I/O 都使用std::basic_streambuf。例如,std::ostringstream 使用 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++ 版本中,您必须:

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

    构造一个标准的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() 方法将不再返回使用默认分配器的标准std::string。它将返回一个std::basic_string,它使用您的自定义分配器。这会在尝试将os.str() 的返回值分配给标准std::string 时出现问题,例如:

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

错误:从 'std::__cxx11::basic_ostringstream, NAlloc>::__string_type aka std::__cxx11::basic_string 转换, NAlloc>' 到非标量类型 'std::__cxx11::string aka std::__cxx11::basic_string' 请求

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

【讨论】:

非常感谢!我真的很喜欢你的解释部分。我也打算为 basic_string 使用自定义分配器。 这适用于无状态分配器。 ostring_stream() ctor 不采用分配器对象,但 stringbuf ctor 采用。因此,您的旧 C++ 示例看起来很有希望。

以上是关于如何在 C++11 中将自定义分配器传递给 std::basic_ostringstream?的主要内容,如果未能解决你的问题,请参考以下文章

如何将自定义分配器的完全相同的状态传递给多个容器?

如何在 C++11 中将 std::string 转换为 std::u32string?

如何从 SQL Server 2014 中的 Select 查询中将数据分配给用户定义的表类型

在 react-router v4 中将自定义道具传递给路由器组件

在 react-router v4 中将自定义道具传递给路由器组件

如何在Objective-C中将孩子分配给父母?