最近我注意到,std::string s
给出了以下陈述:
s.max_size() == s.get_allocator().max_size();
我觉得这很有意思,默认情况下std::string
会使用理论限制为std::allocator<char>
的{{1}}(是的,我知道我假设2的补码,但这与实际无关题)。我知道实际的限制将远远小于此。在典型的32位x86系统上,内核将占用2GB(可能是1GB)的地址空间,从而留下更小的实际上限。
无论如何,GNU libstdc ++的size_type(-1)
似乎返回相同的值,无论它使用的是什么分配器(类似std::basic_string<>::max_size()
)。
所以问题仍然存在,为什么1073741820
不返回std::basic_string<>::max_size()
?在我看来,这是假设的上限。如果分配很短,那么它只会抛出一个get_allocator().max_size()
,为什么不尝试呢?
这更像是一种好奇心,我只是想知道为什么这两者至少在这一个实现中被单独定义。
答案 0 :(得分:10)
在Microsoft Connect中发布了与您的问题相关的错误。微软有一个有趣的答案:
我们已经根据我们对标准的解释将其解析为By Design,它没有明确解释max_size()的预期目的是什么。 Allocator max_size()被描述为“可以有意义地传递给X :: allocate()的最大值”(C ++ 03 20.1.5 [lib.allocator.requirements] / Table 32),但容器max_size()是描述为“最大可能容器的大小()”(23.1 [lib.container.requirements] /表65)。没有描述容器max_size()是否或如何从allocator max_size()派生。多年来我们的实现直接从allocator max_size()派生了容器max_size(),然后将此值用于溢出检查等等。对本标准的其他解释,例如您的解释,是可能的,但对我们来说并非毫无疑问。标准的措辞肯定会从这里的澄清中受益。除非发生这种情况,否则我们决定保留当前实现的原因有两个原因:(1)其他客户可能依赖于我们当前的行为,(2)max_size()从根本上不会购买任何东西。最多,使用分配器(如容器)的东西可以使用allocator max_size()来预测allocate()何时会失败 - 但是简单地调用allocate()是一个更好的测试,因为分配器将决定是否给出内存。使用容器的东西可以使用容器max_size()作为size()大小的保证,但更简单的保证是size_type的范围。
另外here您可以找到核心问题#197。该委员会已考虑要求改进标准的措辞,但它被拒绝了。
所以问题的回答“为什么......?”是标准没有明确解释max_size()的预期目的是什么。
答案 1 :(得分:4)
我不完全确定,但据我所知std::basic_string
在当前标准中不限制将字符串存储在连续内存中。例如,它可以将其存储在几个块中。然后将每个这样的块限制为std::allocator::max_size()
,但总和可能大于该值。
STL容器似乎也是如此。毕竟std::basic_string
是一个容器。
答案 2 :(得分:1)
GCC的实现有一个注释他们如何计算max_size
(一个必须减去内部管家对象的大小,该对象被分配为带有字符串的单个块),然后添加max_size()
返回一个四分之一。没有理由,所以也许只是一个安全边际? (它还应该提供一个绳子类,也许可以用于如此大的弦?)
使用VC ++ max_size()
返回一个小于allocator.max_size()
- 可能是为了解释终止空字符。