size_t 和 std::size_t 之间的区别
Posted
技术标签:
【中文标题】size_t 和 std::size_t 之间的区别【英文标题】:Difference between size_t and std::size_t 【发布时间】:2011-04-28 04:41:41 【问题描述】:size_t
和std::size_t
在声明的位置、应在何时使用以及任何其他区别特性方面有何区别?
【问题讨论】:
我很想知道 C++ 规范是否将 std::size_t 链接到 C size_t 类型。 查看类似问题:link 【参考方案1】:C 的 size_t
和 C++ 的 std::size_t
都是相同的。
在 C 中,它在 <stddef.h>
中定义,而在 C++ 中,它在 <cstddef>
中定义,其内容与 C 标头相同(参见下面的引用)。其定义为 sizeof 运算符的result 的无符号整数类型。
C 标准在 §17.7/2 中说,
size_t 是 sizeof 运算符的结果的无符号整数类型
C++ 标准在 §18.1/3 中说(关于 cstddef
标头),
内容与标准C库头文件相同,有如下改动。
是的,两者都是一样的; 唯一的区别是C++在std
命名空间中定义了size_t
。
还请注意,上面的行还说“有以下更改”,这并不是指size_t
。它更确切地说是指 C++ 对语言(C 中不存在)所做的新添加(大部分),这些添加也定义在同一个标题中。
***有关于 size_t 的范围和存储大小的非常好的信息:
size_t的范围和存储大小
size_t 的实际类型是 平台相关; 常见错误 是假设 size_t 与 unsigned int,这可能导致 移动时出现编程错误,[3][4] 从 32 位到 64 位架构,适用于 例子。
根据 1999 ISO C 标准 (C99),size_t 是无符号数 至少 16 位的整数类型。
其余的您可以从***的this page 阅读。
【讨论】:
这就引出了另一个问题,如果 STL 已经通过 C (cstddef) 导入了 size_t,为什么它又要有自己的另一个版本? @Als: 严格来说,size_t
不带using namespace std;
或using std::size_t;
是错误的。但是,大多数编译器都允许它,标准特别允许它们允许它(§D.5/3)。
@Potatoswatter:当然不能既是错误又不能在标准中明确允许?如果符合标准,那就不是错误!
@BenHymers 该标准规定了标准标头声明的内容,并且不允许它们声明任何其他非保留名称。标头 <cstddef>
可能会或可能不会声明 ::size_t
,因此您不能依赖它存在或不存在,除非特别包含 <stddef.h>
或 C 库中保证声明它的另一个标头。
@Potatoswatter:啊,我明白你的意思了!我一定是被一句话中的太多“允许”弄糊涂了。不过,我仍然认为您的第一条评论太强烈了;正如您刚才所说,::size_t
存在于例如<stddef.h>
中,因此您并不总是需要使用std::
对其进行限定。【参考方案2】:
来自 C++03“17.4.3.1.4 类型”:
对于标准 C 库(脚注 169)中的每个类型 T,类型 ::T 和 std::T 保留给实现,并且在定义时,::T 应与 std::T 相同。
脚注 169:
这些类型是clock_t、div_t、FILE、fpos_t、lconv、ldiv_t、mbstate_t、ptrdiff_t、sig_atomic_t、size_t、time_t、tm、va_list、wctrans_t、wctype_t和wint_t。
【讨论】:
那么可移植代码不应该依赖于定义的std::T
变体吗?
@Mankarse:你不应该依赖它们被定义如果你只包括相应标题的C版本。如果您 #include <stddef.h>
则 std::size_t
可能可用也可能不可用。如果您 #include <cstddef>
则 std::size_t
可用,但 size_t
可能不可用。
@Mankarse:相反。标头的 C++ 版本必须在 std::
中定义它们,并且该段落说它也可以在***命名空间中定义它们,如果是这样,它必须在 std::
和***名称空间中相同地定义它们。大多数编译器只包含 C 头文件并将名称导入到std::
,因此这些符号最终都会在两者中定义。
就个人而言,我从不关心来自 C 岸的 std::
变体。对于标准 C 头文件,我坚持使用 <xxxxx.h>
- 这从来都不是问题。所以,我会使用<stddef.h>
和size_t
并且永远不会再考虑std::size_t
;事实上,我从未想过有(或可能有)std::size_t
。std::size_t其实就是stddef.h的size_t。
cstddef 给出以下内容:
#include <stddef.h>
namespace std
using ::ptrdiff_t;
using ::size_t;
...有效地将先前的定义带入 std 命名空间。
【讨论】:
正如 Nawaz 指出的那样,实际上恰恰相反。您不能包含<cstddef>
并期望获得::size_t
,但如果您包含<stddef.h>
,您将获得std::size_t
。
@MSalters,我不关注。包括<stddef.h>
只会得到::size_t
。
那是你的实现中的一个错误。
@MSalters,我不太明白。不应该反过来吗? <cstddef>
,则保证您会获得std::size_t
,并且您可能还会获得::size_t
(但不能保证)。如果您包含<stddef.h>
,那么您肯定会获得::size_t
,并且您可能还会获得std::size_t
(但不能保证)。它在 C++03 中有所不同,但实际上无法实现并作为缺陷修复。以上是关于size_t 和 std::size_t 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章
std::size_t 与 size_type 作为参数和函数返回类型
std::size_t 还是 std::vector<Foo>::size_type?