为什么编译器允许使用与使用的容器不同的值类型的分配器

时间:2017-05-22 04:30:48

标签: c++ stl containers allocator

似乎C ++ STL容器要求提供的分配器类型的value_type与STL容器的value_type

相同

需要:allocator_- type :: value_type是一样的 作为X :: value_type。

但是,以下使用字符串向量但带有双精度分配器的代码在VS 2012和g ++ 4.4.7上运行正常。在g ++上,valgrind也不会产生任何错误。

int main()
{
  typedef vector<std::string, std::allocator<double> > StringList;
  StringList s;
  for(int i=0; i < 100; i++){
    stringstream ss;
    ss << i;
    s.push_back(ss.str());
  }
  for(StringList::iterator it = s.begin(); it != s.end(); ++it)
    {
      cout << *it << " ";
    }
  cout << endl;

  return 0;
}

我假设分配器内部被反弹到容器的value_type的分配器(虽然我可能错了)。

我的问题是我误读了C ++规范,事实上所有容器都会一直“重新绑定”#34;分配器提供使用他们想要的类型?或者这只是一种常见的做法,但不能保证。

基本上我可以指望这个&#34;功能&#34;容器将始终采用我提供的任何分配器(任何类型)并使其适用于该容器的value_type?

2 个答案:

答案 0 :(得分:5)

如果您尝试使用clang / libc ++构建代码(添加适当的public class HelloWorld implements Initializable { @Override public void initialize(URL url, ResourceBundle resourceBundle) { ... } } includes,则会得到:

  

/ Sources / LLVM / llvm / projects / libcxx / include / vector:474:5:错误:   static_assert失败&#34; Allocator :: value_type必须与         VALUE_TYPE&#34;       static_assert((is_same ::值),

无论如何,标准对此非常清楚(在c ++ 11/14 / 1z中 - 但不是c ++ 03):

using namespace std;

因此,如果您尝试实例化*Requires:* `allocator_type::value_type` is the same as `X::value_type` ,则会得到未定义的行为 - 并且&#34;似乎工作正常&#34;是一个特别繁琐的未定义行为版本。但实际上,它现在似乎工作得很好&#34;

答案 1 :(得分:0)

当你编写自己的分配器时,你原则上可以在分配器中使用与你的类型特征不同的value_type。

从C ++ 11开始,提供了一种类型特征来检查类型T是否具有可以转换为传递的分配器的allocator_type。如果未提供此转换(或编译器未检查),则表明存在未定义的行为。

在MSVC 14.1中,转换是通过简单的重新绑定

完成的
    template<class _Other>
    struct rebind
    {   // convert this type to allocator<_Other>
    typedef allocator<_Other> other;
    };

所以在MSVC中它确实做了内部反弹,至于你的上一个问题,我不会依赖这种实现保持这种方式,当然不会跨越不同的编译器。另外我想知道你为什么要依赖它,而不是给出正确的类型特征?