std::basic_string<_CharT>字符串的最大长度是多少?

3

我想知道如何在给定平台(C ++中)为字符串的长度设置上限。

我仔细研究了很多库,它们大多数是任意定义的。 GNU C ++ STL(带有实验性C ++ 0x功能的那个)有相当明确的定义:

size_t npos = size_t(-1); /*!< The maximum value that can be stored in a variable of type size_t */
size_t _S_max_len = ((npos - sizeof(_Rep_base))/sizeof(_CharT) - 1) / 4; /*!< Where _CharT is a template parameter; _Rep_base is a structure which encapsulates the allocated memory */

以下是我的理解公式的方式:
  • size_t类型必须容纳分配给字符串的单元数(其中每个单元的类型为_CharT)
  • 从理论上讲,type size_t可以容纳的最大值是可分配的1字节单元总数(即char类型)
  • 前一个值减去跟踪分配内存所需的开销(_Rep_base),因此是字符串中单元的最大数量。将该值除以sizeof(_CharT),因为_CharT可能需要超过一个字节的空间
  • 从前一个值中减去1以计算终止字符
  • 最后,还需要除以4。我完全不知道为什么!

我查看了很多地方来寻找解释,但无法在任何地方找到令人满意的解释(这就是为什么我一直在尝试编写代码!如果我错了,请纠正我!!)。


如果它们正在除以2,我猜想是为了将2个字符串长度相加,或将容量增加一倍以进行指数增长,并确保结果不会溢出size_t。基本上这是一个便利操作,以便在分配之前执行无溢出检查,以确保结果仍在范围内,而无需针对每个计算检查溢出。但是我不清楚4是什么意思。 - Steve Jessop
4个回答

3

来自GCC 4.3.4的basic_string.h中的注释如下:

    // The maximum number of individual char_type elements of an
    // individual string is determined by _S_max_size. This is the
    // value that will be returned by max_size().  (Whereas npos
    // is the maximum number of bytes the allocator can allocate.)
    // If one was to divvy up the theoretical largest size string,
    // with a terminating character and m _CharT elements, it'd
    // look like this:
    // npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT)
    // Solving for m:
    // m = ((npos - sizeof(_Rep))/sizeof(CharT)) - 1
    // In addition, this implementation quarters this amount.

特别要注意最后一行,“此外,此实现将此金额划分为四个部分。” 我理解这意味着除以四是完全随意的
我尝试在basic_string.h的签入日志中找到更多信息,但它只追溯到2000年10月5日,并且该注释已经存在于该修订版本中,我对该代码库不熟悉,因此不知道该文件在移动到其当前位置之前可能存放在源树的哪个位置。

@Eric:感谢信息!显然,GCC 4.4.0的basic_string.h中缺少此特定注释(我想知道为什么!)。“任意”的确解释了我对basic_string的一些疑问。 - themoondothshine

0
您可以创建一个包含std::string的小包装类。公开您关心的接口函数。如果任何函数调用会使您的字符串超出所需的最大长度,您可以抛出异常或触发错误。
这旨在实现您的目标(在不深入解析标准库实现的情况下固定字符串的最大长度)。

是的,当然可以。事实上,在__gnu_cxx命名空间中有一个专门用于此目的的函数(我认为它是__gnu_cxx::__throw_length_exception或类似的名称)!问题是我知道如何处理它,但我想知道为什么。 - themoondothshine

0

如果您不介意在运行时进行检查,可以调用std::string::max_size,它返回字符串的最大可能长度。这不会给您任何关于其结果的原因(我不知道GNU代码中的/4是什么),但至少它会给您一些明确的东西来处理。

虽然这不是一个静态函数,但确定每个字符串的正确值可能需要一些小心和/或特定于系统的代码。(例如,VC++字符串似乎将其分配器推迟到此信息。这意味着,如果它们使用不同的分配器,则不同的字符串可能具有不同的最大大小。)


嗯...这可能是可能的。然而,使用GCC时,这个值与分配器有些独立。它取决于typedef allocator::size_type,几乎总是解析为标准的size_t类型。 - themoondothshine

0
实际限制可能比绝对限制要小得多。例如,内存分配将失败。实际限制事先无法真正知道。

所以我认为除数4是任意选择的,或者基于实践经验;这是一种防止溢出的安全措施吗? - themoondothshine

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