std::size_t 还是 std::vector<Foo>::size_type?

Posted

技术标签:

【中文标题】std::size_t 还是 std::vector<Foo>::size_type?【英文标题】:std::size_t or std::vector<Foo>::size_type? 【发布时间】:2017-12-23 10:20:51 【问题描述】:

当我在std::vector&lt;Foo&gt;(或每个具有随机访问迭代器的容器)上循环时,我使用一个无符号整数变量i。如果我想尊重规范,我应该使用std::size_t还是容器本身给出的类型:std::vector&lt;Foo&gt;::size_type

如果我选择std::size_t(出于可读性原因),我能否确定std 命名空间中每个容器的每个实现都使用std::size_t 作为size_type

注意:我只使用 C++98(出于兼容性原因)。

【问题讨论】:

不,你不能确定。如果您想避免可能的缩小转换,请使用容器提供的类型。 在 64 位 Linux 机器上,size_t 可以是 unsigned long 的 typedef 和 std::vector::size_type 可以是 unsigned long long。两者都是 64 位宽,范围相同,但类型不同。 (example) 您可以使用模板类,根据std::size_tstd::vector&lt;T&gt;::size_type 是否具有相同的大小来选择要使用的类型(我现在无法尝试实现它,但我'我很确定这是可行的)。 @NathanOliver :最初,我有这种反应是因为我在任何地方都错误地使用了unsigned long int(可以使用gcc,std::size_tunsigned long int)。现在我在使用std::size_tunsigned long long int 的英特尔编译器移植到Windows 时遇到了兼容性问题。 :-/ 【参考方案1】:

std::vector&lt;Foo&gt;::size_typestd::size_t 相同并不一定正确。即使对于 C++11 也是如此。

但我个人将std::size_t 用于std::vector 索引,而与类型无关。

如果你感觉特别勤奋,你总是可以使用静态断言。显然,static_assert 是 C++98 中后来添加的内容,但在该标准中,您可以使用类似

static char wrong_size_1[1 + sizeof(std::size_t) - sizeof(std::vector<Foo>::size_type)];

static char wrong_size_2[1 - sizeof(std::size_t) + sizeof(std::vector<Foo>::size_type)];

如果类型类型大小不同,则会导致编译时失败。

【讨论】:

实际上,我已经在 boost 中使用了静态断言。好主意! 哇。 Boost 仍然支持 C++98!你知道,它们是好鸡蛋。 我将 boost 1.57 与 GCC 4.4.7 一起使用,没有任何(已知)问题。 ;-)【参考方案2】:

我可以确定 std 命名空间中每个容器的每个实现都使用 std::size_t 作为 size_type 吗?

不,你不能。但是在实践中,您可以相信std::size_t 对于基于单个数组的向量或任何其他容器来说足够大,因为

size_t 可以存储理论上可能的任意类型(包括数组)对象的最大大小。

【讨论】:

对象的最大尺寸很可能远大于向量的最大size_type。当 T 是向量中的内容时,std::vector&lt;&gt;::type 的范围仅为 0 到 numeric_limits&lt;size_t&gt;::max() / sizeof(T)。我要说的是,这种担心可能会缩小转换范围。 @StoryTeller 如果您的整数太小而无法索引向量的对象,我会担心。 std::size_t 至少和它需要的一样大,所以它可以代表任何索引。在最坏的情况下,它会浪费一点点内存。 如果它太小,您将有无法访问的元素。如果它太大,你会“环绕”并可能在错误的地方修改元素。我认为一个比另一个更容易捕获。缩小转换范围有点邪恶。 @StoryTeller 你从哪里得到这个“环绕”的值?因为它比size_type 的大小要大,所以它不可能是一个有效的索引,所以你不可能得到这个元素。使用size_type 不会更容易解决错误,它只是将环绕点移动到另一段代码。 “它不可能是一个有效的索引”。除了 C++ 将愉快地执行隐式缩小转换。对于无符号整数,它被很好地定义为模 2 到某个幂。因此包装。

以上是关于std::size_t 还是 std::vector<Foo>::size_type?的主要内容,如果未能解决你的问题,请参考以下文章

“std::size_t”在 C++ 中有意义吗?

<cstdint> 与 std::size_t 类型

没有匹配函数调用‘std::set<unsigned int>::insert(std::size_t&)

std::size_t 与 size_type 作为参数和函数返回类型

将 opengl Window 转换为 std::size_t 并再次在 Linux 中有效,但在 OS X 中无效

如何定义自定义跨平台 size_t 类型?