为什么std::string::max_size不是一个编译时常量?

34

std::string 提供了一个 max_size() 方法来确定它可以包含的元素的最大数量。

然而,要想在一般情况下计算字符串的最大长度,程序员必须创建一个(可能为空的)字符串对象。

如果该类不需要任何来自程序员的信息,为什么不能将 max_size() 提供为编译时常量?是否有某种运行时信息对于字符串计算其最大大小是必要的?


1
你需要创建一个空字符串的逻辑是不成立的(因为底层分配器已经持有了这个信息)。而且max_size()不是一个常量值。它是当前可以分配的最大值(这取决于分配器状态的运行时变化)。 - Martin York
@Loki:你能提供一下你说话的依据吗?我问这个是因为我相当确定你是错的(就字符串而言max_size;对于分配器来说又是另外一回事)。 - Nemo
1
@Nemo:标准中没有说明它是常量。但在某些实现中,它可能是常量。(我在这里假设)如果标准委员会希望它成为常量,他们会像std::string::npos一样将其设置为const成员变量,但为了提供更多的灵活性,它是一个方法。 - Martin York
@LokiAstari:“如果标准委员会想要的话……他们本来就会……”我猜当他们忘记声明std::vector的内存连续时,你不在场。那异常规范呢?他们不是神,也会出错。C++03标准只说(23.1)“最大可能容器的size()”,并且应该具有O(1)。在我看来,这相当模糊,并且留下了很多关于它的推测空间。 - sbi
4个回答

22

其中一个原因是max_size函数并不是非常有用,委员会认为修复它不值得麻烦。因此,它只是保留了现有状态,因为它是文档化接口的一部分。

请参阅库缺陷报告#197:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3440.html#197

max_size()在很多情况下都没有用,而现有的措辞已经足够清晰,适用于max_size()可以使用的少数情况。尝试更改现有措辞的所有尝试都没有带来改进。


1
+1. 这确实是一个相当无用的函数。std::string::max_size() 返回的是“如果有足够的内存,它可能容纳的最大字符串长度”。很惊讶这里有这么多错误的答案。 - Maxim Egorushkin
尽管如此,在C++20中,std::string::max_size()仍然被定义为constexpr。 - BoP

18

std::string::max_size() 调用 std::allocator::max_size()

根据标准的20.9.6.1.10:

size_type max_size() const noexcept;

返回:对于从调用 allocate(N,0) 可能成功的最大值 N。

(请参考:allocator::max_size)

理论上,分配器实现可以通过系统调用计算出它可以分配的内存块的最大大小。这将有助于确定特定进程中字符串的最大可能大小。


6
标准不要求字符串的max_size调用分配器的max_size。标准对于string的描述指的是第23.1节中的"容器要求",该节将max_size定义为"可能的最大容器的size()"。它根本没有涉及到分配器,因此这个回答是错误的。 - Nemo

5

调用max_size()的操作被委托给用于容器的分配器。

理论上,非常聪明的分配器可以在运行时计算其max_size,例如,取决于可用的RAM。


1
不,根据标准,它并没有委托给分配器。也许在您特定的实现中是这样的,但这与问题无关。如果规范中有任何关于容器将此调用委托给其分配器的内容,请引用出来,我会撤销我的投票。 - Nemo
@Nemo:是的,按照标准,string::max_size()不需要这样做。我在谈论可能的实现方式。 - Andriy

0

这个也应该可以工作:

enum : std::string::size_type {
    npos     = std::string::size_type(-1),
    max_size = npos - 1
};

你所暗示的已经存在于std::string::npos中,它与max_size不同。 - leetNightshade
此外,在x86上,max_size的结果最多为size_type(-2),因为size_type(-1)被认为是无效大小(npos)。 - leetNightshade
@leetNightshade 没错。已修复。 - StackedCrooked

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接