如何在 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++ 版本中,您必须:
定义 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()
方法将不再是 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 使用的每种类型的数据容器。
我想使用自定义分配器从空闲列表中为 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++ 版本中,您必须:
定义
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()
方法将不再是 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 使用的每种类型的数据容器。