为什么 std::string::max_size "strange" 的值是 ?
Why is the value of std::string::max_size "strange"?
我查看了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
?
总的来说,我想知道,一个实施会因为什么原因不使用所有的空间?
其中一个索引是为std::string::npos
值保留的,它表示某些字符串函数中的"未找到"结果。此外,字符串在内部以null终止,因此必须为null终止字符保留一个位置。
这使我们达到了标准库可以提供的radix^bits - 3
的理论最大值(除非这些保留位置可以共享相同的值;我不能100%确定这是不可能的)。据推测,该实现已经选择为内部使用再保留两个索引(或者我错过了一些必须保留的位置)。我可以想象,这种保留索引的一个潜在用途可能是溢出陷阱,它可以检测越界访问。
从实际角度来看:std::string::size_type
通常与地址空间的宽度相同,在这种假设下,无论如何都不可能将整个地址空间用于单个字符串。因此,图书馆报告的数字通常是无法实现的;它只是标准库实现设置的上限,字符串的实际大小限制受到其他来源的限制,通常是可用RAM的数量。
除了eerorika写的…
- 字符串可以(在多种情况下也可以)使用"奇怪"的布局。例如,在GCC 5的C++11一致字符串实现之前,
std::string
被实现为指向堆块(1)的单指针,该堆块包含字符数据和可能的NUL终止符,从指向的地址开始,但该字符数据的前面有大小、容量和引用计数(用于写时复制,也称为COW) - 一般来说,只有一种方法可以知道具体实现在做什么——查看其源代码
- 需要实现来提供
max_size()
,并激励使max_size
看起来足够大以用于实际目的。然而,它们往往提供不切实际的巨大价值。例如,从32位平面内存模型的实际角度来看,即使是2^32-5的数字也显得荒谬,因为它会假设程序的整个其余部分占用4个字节或更少(其中一个字节分配给字符串的NUL终止符)。AMD64上的2^62数字同样荒谬,因为即使是假设的完全实现的长模式(即需要未来的CPU)也"只"支持2^52个不同的物理地址(从技术上讲,交换或RAM压缩可以工作,但这真的是目的吗?)。顺便说一句,之所以选择2^62,而不是2^64减去一些小整数,是因为实现者至少意识到内核将始终保留部分虚拟地址空间用于其自身目的
长话短说……他们必须提供价值,所以他们这样做了,但他们不够关心,无法使其准确和有意义。至少您可以假设比max_size()
长的字符串是绝对不可能的。
(1) :通常情况下,静态分配的空字符串是物理上很小但概念上很大的异常。
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 大于65535的C++数组[size]引发不一致的溢出
- 为什么(-1)%vector::size()总是返回0
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 循环中的条件:为什么每次都调用strlen(),而vector.size()只调用一次
- 为什么这个 std::queue/指向结构的指针列表直到 List.Size() == 0 才释放内存?
- 在函数中使用 const int size 参数创建数组会在 Visual Studio 中抛出错误 C++:表达式的计
- vector.size() 在比较中意外工作
- vector.back() 和 vector[vector.size() - 1] 之间的区别?
- 返回 str vs. str.substr(0,str.size()) 在 leetcode 中给了我不同的输出
- 为什么 GCC 不能假设 std::vector::size 在这个循环中不会改变?
- 为什么"(!v.empty())"比"(v.size() >0)"好?
- 迭代器库中的 std::size() 不适用于传递给函数的 C 样式数组
- std::string.size() 未知行为
- 为什么gmp会在这里与"invalid next size"重新定位一起崩溃?
- 为什么我会"Invalid read of size 8"?(瓦尔格林德)
- 从 std::string 到 std::array<char,size> 的 memcopy 额外数据是否是一种未定义的行为?
- 使用 std::size 来自非 const 上下文
- "fast"或"normal"在"free(): invalid next size (fast)"中是什么意思?
- 行 - " vector<int> used(adj.size(), 0); "是什么意思?