[英]why custom allocator for std::string does not work
I define a new allocator like this:我这样定义一个新的分配器:
template <class T>
class CodecAlloc: public std::allocator<T> {
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
CodecAlloc() {}
CodecAlloc(const CodecAlloc&) {}
pointer allocate(size_type n, const void * = 0) {
T* t = (T*) malloc(n * sizeof(T));
std::cout
<< " used CodecAlloc to allocate at address "
<< t << " (+)" << std::endl;
return t;
}
void deallocate(void* p, size_type) {
if (p) {
free(p);
std::cout
<< " used CodecAlloc to deallocate at address "
<< p << " (-)" <<
std::endl;
}
}
template <class U>
struct rebind { typedef CodecAlloc<U> other; };
};
if I typedef a new type:如果我 typedef 一个新类型:
typedef std::basic_string<char, std::char_traits<char>, CodecAlloc<char>> String;
it work well,CodecAlloc::allocate has been called.它运行良好,CodecAlloc::allocate 已被调用。 but now there is a interface like this:但是现在有一个这样的界面:
void SetBinary(const std::string&)
it's parameter is a std::string, the type String
does not match.它的参数是一个 std::string, String
类型不匹配。 So I use this way to construct std::string
所以我用这种方式来构造std::string
std::string str = std::string("Hello !!", CodecAlloc<char>);
SetBinary(str)
but the CodecAlloc allocator does not been called?.但是没有调用 CodecAlloc 分配器? why.为什么。 and how should i solve this problem.以及我应该如何解决这个问题。 the SetBinary interface can not be changed. SetBinary 接口无法更改。 thks谢谢
So, the line所以,线
std::string str = std::string("Hello !!", CodecAlloc<char>);
is just wrong and has several errors:是错误的并且有几个错误:
CodecAlloc<char>
since that is a type.您不能使用CodecAlloc<char>
因为那是一种类型。 You need to pass an allocator instance, so at least CodecAlloc<char>()
is needed.您需要传递一个分配器实例,因此至少需要CodecAlloc<char>()
。std::string
.如果 1. 是固定的,它仍然无法工作,因为传递的分配器与std::string
使用的分配器不同。 You could fix it to use your type String
: std::string str = String("Hello,;", CodecAlloc<char>);
您可以修复它以使用您的类型String
: std::string str = String("Hello,;", CodecAlloc<char>);
, but that won't work, since std::string
does not have an assigment operator from a type with a different allocator - see this ,但这不起作用,因为std::string
没有来自具有不同分配器的类型的赋值运算符 - 请参阅此So with the detailed explanation above the answer is - no you cannot achieve what you want and pass a custom typedef'ed std::basic_string
in a std::string
and preserve your custom allocator.因此,通过上面的详细解释,答案是 - 不,您无法实现您想要的并在std::string
中传递自定义类型定义的std::basic_string
并保留您的自定义分配器。
std::string str = std::string("Hello !!", CodecAlloc<char>);
Assuming that you actually created a temporary like CodecAlloc<char>()
(because otherwise it wouldn't compile) what happens is that you call the constructor taking a const std::allocator<char>&
(because that's what std::string::allocator_type
is) and your object has that as a base class.假设您实际上创建了一个像CodecAlloc<char>()
这样的临时文件(因为否则它不会编译)会发生什么是您调用构造函数并采用const std::allocator<char>&
(因为这就是std::string::allocator_type
是),并且您的 object 以 class 为基础。 So the reference binds to the base subobject of your CodecAlloc<char>
temporary, and then that base subobject gets copied into the string's internal allocator object.因此,引用绑定到CodecAlloc<char>
临时的基本子对象,然后将该基本子对象复制到字符串的内部分配器 object 中。
You can't make std::string
use a different allocator type just by passing it to the constructor, the allocator type is a static property of the string.您不能仅通过将std::string
传递给构造函数来使用不同的分配器类型,分配器类型是字符串的 static 属性。
I have bad news for you.我有坏消息要告诉你。
The other answers already covered this nicely, but I wanted to be more explicit about this: you will not be able to use this interface with a string that uses a custom allocator .其他答案已经很好地涵盖了这一点,但我想对此更加明确:您将无法将此接口与使用自定义分配器的字符串一起使用。 Or with any other kind of string, for that matter.或者使用任何其他类型的字符串,就此而言。
To understand why, you need to know what std::string
is.要了解原因,您需要知道std::string
是什么。 If you look for "string" on cppreference, you'll be directed to the page for std::basic_string
.如果您在 cppreference 上查找“字符串”,您将被定向到std::basic_string
页面。 This is intentional, std::basic_string
is a template that defines a collection of string classes, and std::string
is one of them.这是故意的, std::basic_string
是一个定义字符串类集合的模板, std::string
就是其中之一。
If you look at the definition of std::string
, you'll see that it is defined as std::basic_string<char>
, which is a shortcut for std::basic_string<char, std::char_traits<char>, std::allocator<char>>
.如果您查看std::string
的定义,您会发现它被定义为std::basic_string<char>
,这是std::basic_string<char, std::char_traits<char>, std::allocator<char>>
。 This means that std::string
already comes embedded with its own allocator , which is not extensible: the member functions std::allocator<T>::allocate
and std::allocator<T>::deallocate
are not virtual.这意味着std::string
已经嵌入了它自己的 allocator ,这是不可扩展的:成员函数std::allocator<T>::allocate
和std::allocator<T>::deallocate
不是虚拟的。 Assuming you wanted to use this constructor from std::basic_string
:假设您想从std::basic_string
使用这个构造函数:
basic_string( const CharT* s, const Allocator& alloc = Allocator() );
... that means that even if the constructor is using a reference to the allocator, these functions ( allocate
and deallocate
) will not be overridden: the constructor doesn't even know about your version of them. ...这意味着即使构造函数使用对分配器的引用,这些函数( allocate
和deallocate
)也不会被覆盖:构造函数甚至不知道您的版本。 Instead, it will use the versions from the base class.相反,它将使用来自基本 class 的版本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.