嵌套容器的分配器

时间:2018-06-04 21:03:49

标签: c++ nested allocator

关于 CppCon talk分配器后,我遇到了following piece of code

#include <iostream>
#include <string>
#include <utility>
#include <vector>

namespace {

template <typename T>
class MyAllocator {
 public:
  using value_type = T;

  MyAllocator(std::string iType) : _type(std::move(iType)) {}

  T* allocate(const std::size_t iNo) { return new T[iNo]; }
  void deallocate(T* iPtr, const std::size_t) { delete[] iPtr; }

  constexpr bool operator!=(const MyAllocator& oth) const {
    return _type != oth._type;
  }

  const std::string& getType() const noexcept { return _type; }

 private:
  std::string _type;
};

using MyString =
    std::basic_string<char, std::char_traits<char>, MyAllocator<char>>;

}  // anonymous namespace

int main(int, char**) {
  ::MyString str1(::MyAllocator<char>("ForStr1"));
  ::MyString str2(::MyAllocator<char>("ForStr2"));
  ::MyString str3(::MyAllocator<char>("ForStr3"));

  std::vector<::MyString> aVector;
  aVector.reserve(1024);

  aVector.push_back(str1);
  aVector.push_back(str2);

    std::cout << "[0]: " << aVector[0].get_allocator().getType() << "\n"
              << "[1]: " << aVector[1].get_allocator().getType() << "\n";


  aVector.insert(aVector.begin(), str3);

  const auto& type0 = aVector[0].get_allocator().getType();
  const auto& type1 = aVector[1].get_allocator().getType();
  const auto& type2 = aVector[2].get_allocator().getType();

  std::cout << "[0]: " << type0 << "\n"
            << "[1]: " << type1 << "\n"
            << "[2]: " << type2 << "\n";

  return 0;
}

我想这里的一般主题是关于嵌套容器中的&#34; 分配器&#34;。虽然从功能上讲,我遇到了问题,但我无法理解代码中发生了什么。

在代码中,我们有一个自定义的 allocator ,它本质上就像默认的分配器,除了它在内部存储一种数据。

我使用相同分配器的三个不同实例构建三个不同的字符串:

using MyString = 
    std::basic_string<char, std::char_traits<char>, MyAllocator<char>>;

::MyString str1(::MyAllocator<char>("ForStr1"));
::MyString str2(::MyAllocator<char>("ForStr2"));
::MyString str3(::MyAllocator<char>("ForStr3"));

现在我有一个简单的std::vector<MyString>

std::vector<::MyString> aVector;
aVector.reserve(1024);

我保留了空格以避免重新分配

现在我推送前两个字符串:

aVector.push_back(str1);
aVector.push_back(str2);

std::cout << "[0]: " << aVector[0].get_allocator().getType() << "\n"
          << "[1]: " << aVector[1].get_allocator().getType() << "\n";

// As expected, it prints:
//       [0]: ForStr1
//       [1]: ForStr2

印刷的结果是我所期待的。我假设分配器由std::string容器拥有。

然而如果我用以下方法强制进行一些复制/移动(重新排列):

aVector.insert(aVector.begin(), str3);

// Now we have vector be like:
//  [str3:ForStr3]    [str1:ForStr1]    [str2:ForStr2]

然后,与向量内的字符串关联的分配器似乎已损坏:

const auto& type0 = aVector[0].get_allocator().getType();
const auto& type1 = aVector[1].get_allocator().getType();
const auto& type2 = aVector[2].get_allocator().getType();

std::cout << "[0]: " << type0 << "\n"
          << "[1]: " << type1 << "\n"
          << "[2]: " << type2 << "\n";

打印:

[0]: ForStr1
[1]: ForStr2
[2]: ForStr2

我期待:

[0]: ForStr3
[1]: ForStr1
[2]: ForStr2

为什么会这样?我错过了 UB 吗? 与std::string相关联的分配器是对象本身的一部分,不是吗?

0 个答案:

没有答案