在我继承的一些代码中,我看到size_t
经常使用std
命名空间限定符。例如:
std::size_t n = sizeof( long );
当然,编译并运行良好。但对我来说这似乎是不好的做法(也许从C继续?)。
size_t
是否构建在C ++中,因此在全局命名空间中是不是真的?是否需要在C ++中使用size_t
包含头文件?
提出这个问题的另一种方法是,是否需要在所有C ++编译器上编译以下程序(包含 no )?
size_t foo()
{
return sizeof( long );
}
答案 0 :(得分:129)
对于这个
,stackoverflow人群之间似乎存在混淆 ::size_t
在向后兼容标头stddef.h
中定义。它从一开始就是ANSI/ISO C
和ISO C++
的一部分。每个C ++实现都必须附带stddef.h
(兼容性)和cstddef
,其中只有后者定义std::size_t
而不一定::size_t
。见C ++标准的附录D.
答案 1 :(得分:41)
C ++标准第17.4.1.2节第4段规定:
“但是,在C ++标准库中,声明和定义(在C中定义为宏的名称除外)都在命名空间std的命名空间范围(3.3.5)内。”
这包括在模式 cname 的标题中找到的项目,包括 cstddef ,它定义了size_t。
所以std :: size_t实际上是正确的。
答案 2 :(得分:13)
您可以在全局命名空间中获取size_t
,例如,<stddef.h>
代替<cstddef>
。我看不到任何明显的好处,并且该功能已被弃用。
答案 3 :(得分:4)
size_t没有内置到C ++中。它没有默认定义。这个不用GCC编译:
int main(int argc, char** argv) {
size_t size;
}
也就是说,size_t是POSIX的一部分,如果你只使用像<cstdlib>
这样的基本内容,你可能最终会定义它。
你可以说std :: size_t是size_t的C ++等价物。正如Brian指出的那样,std ::被用作命名空间以避免设置不适合所有人的全局变量。它就像std :: string,它也可以在根命名空间中定义。
答案 4 :(得分:4)
std::size_t n = sizeof( long );
实际上,你还没有问过上面有什么具体的坏习惯。使用size_t,使用std命名空间进行限定,......
正如C ++标准所说(18.1),size_t是标准头中定义的类型。我建议放弃有关C语言可能继承的任何想法和印象。 C ++是一种独立且不同的语言,最好将其视为一种语言。它有自己的标准库,C ++标准库的所有元素都在命名空间std中定义。但是,可以在C ++程序中使用C标准库的元素。
我考虑将其列为肮脏的黑客。 C ++标准规定标题的内容相同或基于C标准库中的相应标题,但在大多数情况下,已应用更改。换句话说,它不是直接副本和将C标头粘贴到C ++标头中。
size_t不是C ++中的内置类型。它是一个定义的类型,用于指定使用哪种整数类型作为sizeof()运算符的返回类型,因为sizeof()的实际返回类型是实现定义的,因此C ++标准通过定义size_t来统一。
将是以下程序(没有 包括)预计将编译 所有C ++编译器?
size_t foo() { return sizeof( long ); }
C ++标准说(1.4):
库中定义的名称具有命名空间范围(7.3)。 C ++转换单元(2.1)通过包含适当的标准库头(16.2)来获取对这些名称的访问。
size_t是在std命名空间中定义的名称,因此在这种情况下,使用此名称的每个程序都应包含相应的标题。
接下来,3.7.3章节说:
但是,引用std,std :: bad_alloc和std :: size_t是不正确的,除非通过包含适当的标题声明了名称。
鉴于此,使用size_t但不包括标题的程序格式不正确。
答案 5 :(得分:2)
有时其他库会定义自己的size_t。例如提升。 std :: size_t指定你肯定想要c ++标准。
size_t是c ++标准类型,它在名称空间std。
中定义答案 6 :(得分:2)
GNU编译器头包含类似
的内容typedef long int __PTRDIFF_TYPE__; typedef unsigned long int __SIZE_TYPE__;
然后stddef.h就像
那样typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef __SIZE_TYPE__ size_t;
最后cstddef文件包含类似
的内容#include <stddef.h> namespace std { using ::ptrdiff_t; using ::size_t; }
我认为应该说清楚。只要你包含&lt; cstddef&gt;你可以使用size_t或std :: size_t,因为size_t是在std命名空间之外的typedefed然后包含的。实际上你有
typedef long int ptrdiff_t; typedef unsigned long int size_t; namespace std { using ::ptrdiff_t; using ::size_t; }
答案 7 :(得分:2)
我认为澄清已经足够清楚了。 std::size_t
在C ++中很有意义,::size_t
在C中很有意义。
但问题仍然存在。即假设::size_t
和std::size_t
兼容是否安全?
从纯粹的类型安全角度来看,它们不一定相同,除非它被定义为必须相同的地方。
我认为很多人正在使用la:
----
// a.hpp
#include <string>
void Foo( const std::string & name, size_t value );
-----
// a.cpp
#include "a.hpp"
using namespace std;
void Foo( const string & name, size_t value )
{
...
}
因此,在标题中,您将在源文件中使用::size_t
,并使用std::size_t
。{{1}}。所以它们必须兼容,对吗?否则你会收到编译错误。
/ Michael S.