分配器:标准容器如何在内部工作?

时间:2016-02-07 16:37:34

标签: c++ stl containers allocator

作为此问题的一个示例,我将使用std::vector 它的定义来自documentation

template<class T, class Allocator = std::allocator<T>>
class vector;

正如预期的那样,如果T是其类型,则分配器应偏向T
无论如何,下面的代码编译没有错误(至少使用GCC)并运行

#include<vector>
#include<memory>
#include<string>

struct S {
    int i;
    double d;
    std::string s;
};

int main() {
    std::allocator<int> alloc;
    std::vector<S, std::allocator<int>> v{alloc};
    v.push_back(S{});
}

在这里,我通过使用专注于 int 的分配器来创建 S 向量

是合法代码吗?我应该期待未定义的行为吗?还有什么?
我不完全明白这背后的魔力以及为什么STL让用户这样做 另一方面,rebind之类的内容仅在std::list的文档中提及,我不知道它们是否也适用于此类案例。

在其他方面,如果它有效,我想知道它为什么有用(它是rebind背后的吗?),否则我想知道为什么允许它。

2 个答案:

答案 0 :(得分:7)

表98 - 可识别分配器的容器要求在第一行中说明:

  

要求: allocator_type::value_typeX::value_type相同

客户端代码违反 Requires 子句会导致未定义的行为。

gcc和VS不会检测到此错误。它们允许代码通过将分配器重新绑定到适当的类型来工作。 libc ++使用static_assert主动检测此错误。

http://melpon.org/wandbox/permlink/LVYEHfVIGoyZsii8

vector的所有三个实现在这方面都是有效的。

libc ++主动检测此错误的基本原理是更快地(并在编译时)为您找到错误。如果在一个大型程序中你有两个向量:vector<int, some_allocator<int>>vector<int, some_allocator<long>>并且程序逻辑假设它们是相同的类型,那将是一件坏事。

答案 1 :(得分:2)

它似乎有效,让我感到惊讶,但是:

你违约了。 allocator必须满足allocator<T>cite cppreference的要求,其中包括:

  

a.allocate(n) |分配适用于n类型T对象的存储,但不构造它们。可能会抛出异常。

std::allocator<int> S sizeof(int)!= sizeof(S)不起作为std::vector

所以,

  

我想知道为什么允许这样做。

这是不允许的。它只是编译器无法检测到的。

@AlbertoM adds

  

要在Allocator::value_type页面中添加来自cppreference的引用:“如果TT不同,则行为未定义。”, keyPos = 0; keySeq = [38,38,40,40,37,39,37,39,66,65]; keySeqUser = [38,38,40,40,37,39,37,39]; var logKeys = function(evt) { key = evt.keyCode ? evt.keyCode : evt.which ? evt.which : evt.charCode; if (keyPos <= 9) { keySeqUser.push(key); keyPos++; } else { keySeqUser = []; keyPos=0; } if (keySeqUser.toString() == keySeq.toString()) { $(".page").hide(); $(".lanes").fadeIn().animate({height: "600px"}, 2000); $(".pin").hide(); setTimeout(function() { $(".pin").show().animate({opacity: 1}, 500); }, 2500); attemptKeyCombo(); } console.log(keySeqUser.toString()); } document.body.addEventListener("keypress", logKeys); 是向量的值类型。

IE中。在您的情况下,行为是未定义的。