根据cppreference.com,size_t
在几个头中定义,即
<cstddef>
<cstdio>
<cstring>
<ctime>
字符串
从C++11开始,
<cstdlib>
<cwchar>
型
首先,我想知道为什么会这样,这不是与DRY原则相矛盾吗?
使用size_t
时,我应该包含上面哪一个头文件?这有关系吗?
根据cppreference.com,size_t
在几个头中定义,即
<cstddef>
<cstdio>
<cstring>
<ctime>
字符串
从C++11开始,
<cstdlib>
<cwchar>
型
首先,我想知道为什么会这样,这不是与DRY原则相矛盾吗?
使用size_t
时,我应该包含上面哪一个头文件?这有关系吗?
4条答案
按热度按时间wmvff8tz1#
假设我想最小化我正在导入的函数和类型,我会选择
cstddef
,因为它没有声明任何函数,只声明了6种类型。其他的专注于特定的域(字符串,时间,IO),可能对你无关紧要。请注意,
cstddef
只保证定义std::size_t
,也就是说,在命名空间std
中定义size_t
,尽管它也可以在全局命名空间中提供这个名称(实际上,普通的size_t
)。相比之下,
stddef.h
(也是C中可用的头文件)保证在全局命名空间中定义size_t
,并且 may 还提供std::size_t
。i7uaboj42#
事实上,几个头文件的概要(包括在C++标准中)专门包括
size_t
以及进一步的头文件定义了size_t
类型(基于C标准,因为<cX>
头文件只是ISO C<X.h>
头文件,并注意到没有删除size_t
的变化)。C++标准然而,引用
<cstddef>
来定义std::size_t
因此,由于
<cstddef>
只引入了类型而没有函数,我坚持使用这个头文件来使std::size_t
可用。注意几点:
1.
std::size_t
的类型可以使用decltype
获得,不包括header如果您打算在代码中引入typedef,(例如,因为您编写了一个容器并希望提供
size_type
typedef),您可以使用全局sizeof
,sizeof...
或alignof
运算符来定义类型,而不包括任何头,因为这些运算符根据标准定义返回std::size_t
,您可以使用decltype
关于他们:字符串
1.
std::size_t
本身不是全局可见的,尽管带有std::size_t
参数的函数是。隐式声明的全局分配和释放函数
型
不要引入
size_t
、std
或std::size_t
,引用
std
或std::size_t
是格式错误的,除非通过包含适当的报头来声明名称。1.用户不能重新定义
std::size_t
,尽管可能有多个typedef引用同一命名空间中的同一类型。虽然
std
中出现size_t
的多个定义是完全有效的,但根据 7.1.3 / 3,不允许向namespace std
添加任何声明 17.6.4.2.1 / 1:如果C++程序将声明或定义添加到命名空间std或命名空间std中的命名空间,则该程序的行为是未定义的,除非另有说明。
为
size_t
添加适当的typedef不会违反 7.1.3,但会违反 17.6.4.2.1 并导致未定义的行为。std
中添加声明或定义(除了一些模板专门化的情况,其中typedef不是模板专门化)。Extending thenamespace std
*vwkv1x7d3#
所有的标准库头文件都有相同的定义;你在自己的代码中包含哪一个并不重要。在我的计算机上,我在
_stddef.h
中有以下声明。这个文件被你列出的每个文件所包含。字符串
s4n0splo4#
你可以不使用header:
字符串
这是因为C++标准要求:
sizeof
和sizeof...
的结果是一个std::size_t
类型的常量。[注:std::size_t
在标准头文件<cstddef>
(18.2)中定义。- end note ]换言之,该标准要求:
型
还要注意的是,在全局和
std
命名空间中声明这个typedef
是完全可以的,只要它匹配相同 typedef-name 的所有其他typedef
声明(不匹配的声明会发出编译器错误)。这是因为:
typedef
说明符可以用来重新定义在该作用域中声明的任何类型的名称,以引用它已经引用的类型。对于怀疑者说这构成了在命名空间
std
中添加新类型,并且这种行为被标准明确禁止,这就是UB,仅此而已;我不得不说,这种态度相当于忽视和否认对潜在问题的更深入理解。标准禁止在命名空间
std
中添加新的声明和定义,因为这样做可能会把标准库弄得一团糟,并把自己的腿踢断。对于标准编写者来说,让用户专门化一些特定的事情并禁止做任何其他事情是更容易的,而不是禁止用户不应该做的每一件事,(和那条腿)。他们在过去要求没有标准容器应该用不完整的类型示例化时就是这样做的,而事实上,一些容器可以很好地做到这一点(参见The Standard Librarian: Containers of Incomplete Types by Matthew H. Austern):.最后,这一切似乎太模糊,太不理解;标准化委员会认为没有任何选择,除了说STL容器不应该与不完整的类型一起工作。为了更好地衡量,我们也将这一禁令应用于标准库的其余部分。
.现在回想起来,现在对这项技术有了更好的理解,这个决定似乎基本上仍然是正确的。是的,在某些情况下,可以实现一些标准容器,以便它们可以用不完整的类型示例化-但很明显,在其他情况下,这将是困难的或不可能的。我们尝试的第一个测试,使用
std::vector
,恰好是个容易的案子考虑到语言规则要求
std::size_t
完全是decltype(sizeof(int))
,执行namespace std { using size_t = decltype(sizeof(int)); }
是不会破坏任何东西的事情之一。在C11之前,没有
decltype
,因此没有办法在一个简单的语句中声明sizeof
结果的类型,而不涉及大量的模板。size_t
在不同的目标体系结构上别名不同的类型,但是,仅仅为sizeof
的结果添加一个新的内置类型并不是一个优雅的解决方案,并且没有标准的内置typedef。因此,当时最可移植的解决方案是将size_t
类型别名放在某些特定的头部和文档中,在C11中,现在有一种方法可以将标准的确切要求写为一个简单的声明。