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

时间:2018-01-23 16:06:24

标签: c++11 stringstream allocator ostringstream

我想使用自定义分配器为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
}
  

错误:&#39; OstringStream {aka std :: basic_string&lt; char,std :: char_traits&lt; char&gt ;, NAlloc&lt; char&gt; &GT;}&#39;不是源于&#39; std :: basic_ostream&lt; _CharT,_Traits&gt;&#39;

1 个答案:

答案 0 :(得分:3)

您的OstringStream类型的typedef为std::basic_string,而不是std::basic_ostream。这就是您从operator<<收到错误的原因。左侧操作数必须是从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 ++版本中,您必须:

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

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

  3. 例如:

    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&lt; char,std :: char_traits&lt; char&gt;,NAlloc&gt; :: __ string_type {aka std :: __ cxx11 :: basic_string&lt; char,std :: char_traits&lt; char&gt; ,NAlloc&gt;}'到非标量类型'std :: __ cxx11 :: string {aka std :: __ cxx11 :: basic_string&lt; char&gt;}''

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