6

最近我注意到以下陈述是不正确的std::string s

s.max_size() == s.get_allocator().max_size();

我发现这很有趣,默认情况下std::string将使用std::allocator<char>理论限制为size_type(-1)(是的,我知道我假设是 2 的补码,但这与实际问题无关)。我知道实际的限制会比这个少得多。在典型的 32 位 x86 系统上,内核将占用 2GB(可能是 1GB)的地址空间,而实际上限要小得多。

无论如何,GNU libstdc++std::basic_string<>::max_size()似乎返回相同的值,而不管它使用的分配器说什么(类似于1073741820)。

所以问题仍然存在,为什么不std::basic_string<>::max_size()直接返回get_allocator().max_size()?在我看来,这是假设的上限。如果分配不足,它只会抛出 a std::bad_alloc,那么为什么不尝试呢?

这比其他任何事情都更令人好奇,我只是想知道为什么这两者至少在这个实现中是分开定义的。

4

3 回答 3

10

Microsoft Connect中发布了与您的问题相关的错误。微软对此有一个有趣的答案:

根据我们对标准的解释,我们已将其作为设计解决,这并没有清楚地解释 max_size() 的预期目的是什么。分配器 max_size() 被描述为“可以有意义地传递给 X::allocate() 的最大值”(C++03 20.1.5 [lib.allocator.requirements]/Table 32),但容器 max_size() 是描述为“最大可能容器的大小()”(23.1 [lib.container.requirements]/Table 65)。没有描述容器 max_size() 是否应该或如何从分配器 max_size() 派生。多年来,我们的实现都是直接从分配器 max_size() 派生容器 max_size(),然后将此值用于溢出检查等。对标准的其他解释(例如您的)是可能的,但对我们来说并非毫无疑问是正确的。该标准的措辞当然可以从这里的澄清中受益。除非发生这种情况,否则我们决定保持当前实现不变,原因有两个:(1) 其他客户可能依赖于我们当前的行为,以及 (2) max_size() 基本上不买任何东西。最多,消耗分配器的东西(如容器)可以使用分配器 max_size() 来预测 allocate() 何时会失败 - 但简单地调用 allocate() 是一个更好的测试,因为分配器将决定是否分配内存。消耗容器的东西可以使用容器 max_size() 作为 size() 大小的保证,但更简单的保证是 size_type 的范围。我们决定保持我们当前的实现不变有两个原因:(1) 其他客户可能依赖于我们当前的行为,(2) max_size() 基本上不买任何东西。最多,消耗分配器的东西(如容器)可以使用分配器 max_size() 来预测 allocate() 何时会失败 - 但简单地调用 allocate() 是一个更好的测试,因为分配器将决定是否分配内存。消耗容器的东西可以使用容器 max_size() 作为 size() 大小的保证,但更简单的保证是 size_type 的范围。出于两个原因,我们决定保持我们当前的实现不变:(1) 其他客户可能依赖于我们当前的行为,以及 (2) max_size() 基本上不买任何东西。最多,消耗分配器的东西(如容器)可以使用分配器 max_size() 来预测 allocate() 何时会失败 - 但简单地调用 allocate() 是一个更好的测试,因为分配器将决定是否分配内存。消耗容器的东西可以使用容器 max_size() 作为 size() 大小的保证,但更简单的保证是 size_type 的范围。消耗分配器的东西(如容器)可以使用分配器 max_size() 来预测 allocate() 何时会失败 - 但简单地调用 allocate() 是一个更好的测试,因为分配器将决定是否分配内存。消耗容器的东西可以使用容器 max_size() 作为 size() 大小的保证,但更简单的保证是 size_type 的范围。消耗分配器的东西(如容器)可以使用分配器 max_size() 来预测 allocate() 何时会失败 - 但简单地调用 allocate() 是一个更好的测试,因为分配器将决定是否分配内存。消耗容器的东西可以使用容器 max_size() 作为 size() 大小的保证,但更简单的保证是 size_type 的范围。

此外,您可以在这里找到核心问题 #197。委员会已考虑改进标准措辞的要求,但被拒绝了。

所以回答你的问题“为什么......?” 是标准没有清楚地解释 max_size() 的预期目的是什么。

于 2009-10-20T06:48:03.130 回答
4

我不完全确定,但据我所知std::basic_string,当前标准不限于将字符串存储在连续内存中。例如,它可以将其存储在几个块中。然后将每个这样的块限制为std::allocator::max_size()但总和可能大于此。

STL 容器似乎也是如此。毕竟std::basic_string是一个容器。

于 2009-10-20T06:14:55.473 回答
1

GCC's implementation has a comment how they calculate max_size (one has to subtract the size of internal housekeeping object which is allocated as a single block with the string), and then adds that max_size() returns a quarter of that. There is no rationale given, so perhaps it is just a safety margin? (It should also provide a rope class, which perhaps one would use for so large strings?)

With VC++ max_size() returns one less than allocator.max_size() - probably to account for terminating null character.

于 2009-10-20T07:02:49.057 回答