我看着std::string::max_size并注意到了这个例子:
#include <iostream>
#include <string>
int main ()
{
std::string str ("Test string");
std::cout << "max_size: " << str.max_size() << "\n";
return 0;
}
输出:
max_size: 4294967291
但是,我一直认为此限制是由于无符号整数/ size_t的最大值所致-因此,我有点希望它是2^32 - 1
,即4294967295
。为什么在此示例中,最大大小不使用这4个字节?
我还尝试运行示例代码,在那台机器上是2^62
-再次使我感到困惑,为什么它不是2^64 - 1
?
总的来说,我想知道,由于什么原因,实现无法使用所有空间?
答案 0 :(得分:6)
其中一个索引(可以表示的最大的索引,更具体一点)保留给std::string::npos
值,该值表示某些字符串函数中的“未找到”结果。此外,字符串在内部是空终止的,因此必须为空终止符保留一个位置。
这使我们达到了标准库可以提供的radix^bits - 3
的理论最大值(除非那些保留的职位可以共享相同的值;我不是100%确信这是不可能的)。大概该实现选择为内部使用保留两个以上的索引(或者我错过了一些必要的保留位置)。我可以想象到的这种保留索引的一种潜在用法可能是溢出陷阱,它可以检测访问超出范围。
从实用的角度来看:std::string::size_type
通常与地址空间相同,在这种假设下,无论如何对于单个字符串都不可能使用整个地址空间。因此,图书馆报告的数字通常无法获得;它只是标准库实现的上限,字符串的实际大小限制受其他来源的限制,通常受可用RAM数量的限制。
答案 1 :(得分:1)
除了eerorika写的是什么...
std::string
被实现为指向包含字符数据以及可能的NUL的堆块(1)的单个指针。终止符,从指向的地址开始,但是字符数据的开头是大小,容量和参考计数(对于写时复制又称为COW)。max_size()
,并进行激励以使max_size
看起来足够大以用于实际目的。但是,它们通常提供的值实在太大。例如,从实际的角度来看,就32位平面内存模型而言,即使2 ^ 32-5的数字也似乎是荒谬的,因为它会假定程序的其余全部占用4个字节或更少的字节(其中一个字节分配给字符串的字节)。 NUL终止符)。同样荒谬的是AMD64上的2 ^ 62数字,因为即使假设的fully implemented long mode(即要求使用将来的CPU)也将“仅”支持2 ^ 52个不同的物理地址(从技术上讲,交换或RAM)压缩可能有效,但这真的是目的吗?)。顺便说一句,之所以选择2 ^ 62 而不是2 ^ 64减去一些小整数,是因为实现者至少意识到内核将始终保留虚拟部分。出于自身目的寻址空间。长话短说……他们必须提供一种价值,所以他们这样做了,但是他们并不在乎使其准确和有意义。至少您可以假设长度超过max_size()
的字符串绝对是不可能的。
(1):好吧,通常–静态分配的空字符串是物理上很小但概念上很大的异常。