C++ std::basic_字符串的最大长度<_图表>;一串

C++ std::basic_字符串的最大长度<_图表>;一串,c++,string,limit,system-dependent,C++,String,Limit,System Dependent,我想知道如何为给定的平台确定字符串长度的上限(在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(_C

我想知道如何为给定的平台确定字符串长度的上限(在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\u t npos=size\u t(-1);/*!<可以存储在类型为size\u t的变量中的最大值*/
大小(npos-sizeof(_Rep_base))/sizeof(_CharT)-1)/4;/*!<其中_CharT是一个模板参数_Rep_base是一种封装已分配内存的结构*/
以下是我对公式的理解:

  • 大小类型必须包含分配给字符串的单位计数(其中每个单位都是图表类型)
  • 理论上,size类型的变量可以接受的最大值是可以分配的1字节(即char类型)的单元总数
  • 因此,前一个值减去跟踪分配内存所需的开销(_Rep_base)就是字符串中的最大单元数。将该值除以sizeof(_-CharT),因为_-CharT可能需要超过一个字节
  • 从上一个值中减去1以说明终止字符
  • 最后,这个除法剩下4。我完全不知道为什么

我在很多地方寻找解释,但在任何地方都找不到令人满意的解释(这就是为什么我一直在努力弥补它!如果我错了,请纠正我!!)。

您可以创建一个包含
std::string
的小包装类。公开您关心的接口函数。如果任何函数调用都会将字符串增加到所需的最大长度之外,则可以引发异常或触发错误


这是为了实现您的目标(确定字符串的最大长度),而无需深入解读标准库实现的混乱情况。

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


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

实际限制可能比绝对限制小得多。例如,内存分配将失败。实际限制不能提前知道。

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.
特别是,请注意最后一行,“此外,此实现将此金额四分之一。”我认为这意味着除以四实际上是完全任意的


我试图在中找到更多信息,但它只能追溯到2000年10月5日,并且此注释已经出现在该修订版中,并且我对该代码库不太熟悉,不知道文件在移动到其当前位置之前可能在源代码树中的位置。

Ya,当然,这绝对没有问题。事实上,_gnu_cxx名称空间中有一个函数就是为了这个(我认为它是_gnu_cxx::_throw_length_exception或其他什么)!问题是我知道如何处理它,但我想知道为什么。如果它们被2除,我猜是这样的,它们可以将2个字符串长度相加,和/或将指数增长的容量增加一倍,并确保结果不会溢出
size\u t
。基本上是一种方便,以便在分配前进行无溢出检查,确保结果仍在边界内,而不必在每次计算时检查溢出。不过我不知道4点的事。嗯。。。这是可能的。然而,对于GCC,这个值在某种程度上独立于分配器。它取决于typedef分配器::size_type,它几乎总是解析为标准size_t类型;防止溢出的安全措施?@Eric:谢谢你的信息!显然,GCC4.4.0的
basic_string.h
(我想知道为什么!)中缺少这条特别的注释“武断”真的解释了我关于基本字符串的一些问题。