简体   繁体   English

为什么 std::string 的自定义分配器不起作用

[英]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:是错误的并且有几个错误:

  1. You can't use 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>()
  2. If 1. is fixed, it will still not work since the passed allocator differs from the one used by std::string .如果 1. 是固定的,它仍然无法工作,因为传递的分配器与std::string使用的分配器不同。 You could fix it to use your type String : std::string str = String("Hello,;", CodecAlloc<char>);您可以修复它以使用您的类型Stringstd::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>::allocatestd::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. ...这意味着即使构造函数使用对分配器的引用,这些函数( allocatedeallocate )也不会被覆盖:构造函数甚至不知道您的版本。 Instead, it will use the versions from the base class.相反,它将使用来自基本 class 的版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM