STL 容器中的 max_size 由什么决定?

Fay*_*ure 7 c++

我试图在 C 中重现 std::string 的行为,但是有一件事我真的不知道该怎么做。有一个max_size成员方法可以提供字符串(或向量等的任何其他数组)可以具有的最大大小,所以我的问题是我知道这个值可能取决于系统,那么容器如何确定这个数字?我可以在 C 中得到它吗?

eer*_*ika 5

STL 容器中的 max_size 由什么决定?

标准库的实现者选择它。考虑到 API 和目标系统的限制,实现者应该设计容器以支持尽可能大的尺寸。容器的实现失败,并且提供的分配器可能会施加额外的限制,理想情况下应该通过降低的(因此更准确)来反映max_size

请注意,这max_size在实践中很少有用。这是一个理论上的上限,实际上不一定可以达到……通常是因为内存不足,至少在 64 位系统上是这样。它用于早期检测明显错误的用户输入(然后相应地抛出异常)。

我可以在 C 中得到它吗?

您可以定义一个常量 extern 变量并在 C++ 翻译单元中对其进行初始化。例子:

// common_header.h
// add header guard here
#include <stdlib.h>

#ifdef __cplusplus
extern "C" {
#endif

extern const size_t cpp_string_max_size;
extern const size_t cpp_vector_int_max_size;

#ifdef __cplusplus
}
#endif

// source.cpp
#include "common_header.h"
#include <string>
#include <cstdlib>
#include <vector>

const std::size_t cpp_string_max_size = std::string{}.max_size();
const std::size_t cpp_vector_int_max_size = std::vector<int>{}.max_size();
Run Code Online (Sandbox Code Playgroud)

然后,使用 C++ 编译器编译 C++ 翻译单元并将其与 C 程序链接。


我正在寻找一种不涉及任何 C++ 的方法

根据“任何 C++”的含义,您可以使用元编程:编写一个 C++ 程序,该程序生成一个 C 源文件,其中包含由 C++ 程序生成的常量。生成部分显然涉及 C++,但生成的源代码将是纯 C 语言,并且只能使用 C 编译器进行编译。

如果这不符合您的喜好,您可以阅读您选择的 C++ 标准库的实现文件,看看它们是如何实现的max_size,然后手动编写 C 源代码。这并不涉及在任何时候编写或编译任何 C++,尽管它确实涉及阅读 C++。


t.n*_*ese 4

max_size定义了该容器的特定实现理论上可以具有的最大大小。

\n

该数字不取决于操作系统或可用内存,而仅由容器的实现给出。

\n

如果您的字符串容器(不std::string兼容)实现如下所示:

\n
struct string {\n   unsigned char size;\n   char *data;\n\n   // \xe2\x80\xa6 further functions \xe2\x80\xa6\n};\n
Run Code Online (Sandbox Code Playgroud)\n

然后max_size可能会指的是可以代表的最大数字unsigned char

\n

如果您的实现只是一个\\0终止的字符串,没有任何其他元信息。然后max_size可能指的是对于给定的目标体系结构,可以通过指针寻址的最大字节数。

\n

所以max_size只是说,容器的实现方式将能够处理max_size多个元素。但它并不能保证操作系统能够做到这一点。

\n
\n

对于实现可以处理的最大字符数的std::string上限由最大数量size_type和一些进一步的约束给出。

\n

for size_typeastd::string本身由使用的分配器 ( ) 给出std::allocator<CharT>,默认为std::allocator_traits<Allocator>::size_type

\n

对于std::allocator裁判员size_type来说std::size_t

\n

因此,对于 a 来说, 的上限std::string是的最大值减去满足字符串其他要求所需的值。max_sizestd::size_tn

\n

oflibstdc++gcc-4.6.2定义是这样描述max_size

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

以及相应的初始化

\n
template<typename _CharT, typename _Traits, typename _Alloc>\n  const typename basic_string<_CharT, _Traits, _Alloc>::size_type\n  basic_string<_CharT, _Traits, _Alloc>::\n  _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4;\n
Run Code Online (Sandbox Code Playgroud)\n

根据此197. max_size() underspecified(不确定是否有更新的更新), 的值max_size不会因调用而改变:

\n
\n

LWG 很清楚 max_size() 返回的值在每次调用时都不会改变。

\n
\n

因此,您可以使用eerorika的方法来获取特定分配器的值。

\n