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<Foo>
(或每个具有随机访问迭代器的容器)上循环时,我使用一个无符号整数变量i
。如果我想尊重规范,我应该使用std::size_t
还是容器本身给出的类型:std::vector<Foo>::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_t
和std::vector<T>::size_type
是否具有相同的大小来选择要使用的类型(我现在无法尝试实现它,但我'我很确定这是可行的)。
@NathanOliver :最初,我有这种反应是因为我在任何地方都错误地使用了unsigned long int
(可以使用gcc,std::size_t
是unsigned long int
)。现在我在使用std::size_t
是unsigned long long int
的英特尔编译器移植到Windows 时遇到了兼容性问题。 :-/
【参考方案1】:
std::vector<Foo>::size_type
与std::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<>::type
的范围仅为 0 到 numeric_limits<size_t>::max() / sizeof(T)
。我要说的是,这种担心可能会缩小转换范围。
@StoryTeller 如果您的整数太小而无法索引向量的对象,我会担心。 std::size_t
至少和它需要的一样大,所以它可以代表任何索引。在最坏的情况下,它会浪费一点点内存。
如果它太小,您将有无法访问的元素。如果它太大,你会“环绕”并可能在错误的地方修改元素。我认为一个比另一个更容易捕获。缩小转换范围有点邪恶。
@StoryTeller 你从哪里得到这个“环绕”的值?因为它比size_type
的大小要大,所以它不可能是一个有效的索引,所以你不可能得到这个元素。使用size_type
不会更容易解决错误,它只是将环绕点移动到另一段代码。
“它不可能是一个有效的索引”。除了 C++ 将愉快地执行隐式缩小转换。对于无符号整数,它被很好地定义为模 2 到某个幂。因此包装。以上是关于std::size_t 还是 std::vector<Foo>::size_type?的主要内容,如果未能解决你的问题,请参考以下文章
没有匹配函数调用‘std::set<unsigned int>::insert(std::size_t&)
std::size_t 与 size_type 作为参数和函数返回类型