63

在我继承的一些代码中,我看到经常使用size_t命名std空间限定符。例如:

std::size_t n = sizeof( long );

当然,它编译并运行良好。但这对我来说似乎是一种不好的做法(也许是从 C 继承而来的?)。

这不是size_t内置在 C++ 中并因此位于全局命名空间中吗?size_t是否需要在 C++中使用头文件?

问这个问题的另一种方法是,以下程序(没有包含)是否可以在所有 C++ 编译器上编译

size_t foo()
{
    return sizeof( long );
}
4

8 回答 8

135

stackoverflow 人群中似乎对此感到困惑

::size_t在向后兼容标头中定义stddef.h。它从一开始就是其中的ANSI/ISO C一部分ISO C++。每个 C++ 实现都必须附带stddef.h(兼容性),cstddef并且只有后者定义std::size_t而不一定::size_t。请参阅 C++ 标准的附录 D。

于 2008-11-12T04:18:55.753 回答
41

C++ 标准的第 17.4.1.2 节第 4 段指出:

“然而,在 C++ 标准库中,声明和定义(在 C 中定义为宏的名称除外)在命名空间 std 的命名空间范围 (3.3.5) 内。”

这包括在模式cname的标题中找到的项目,包括定义 size_t的cstddef 。

所以 std::size_t 实际上是正确的。

于 2008-10-26T02:21:18.853 回答
13

例如,您可以size_t通过包含<stddef.h>而不是<cstddef>. 我看不到任何明显的好处,并且该功能已被弃用。

于 2008-10-26T11:12:02.200 回答
4

size_t 没有内置在 C++ 中。并且默认情况下没有定义。这个不能用 GCC 编译:

int main(int argc, char** argv) {
size_t size;
}

也就是说, size_t 是 POSIX 的一部分,如果你只使用基本的东西,比如<cstdlib>,你最终可能会定义它。

您可能会争辩说 std::size_t 是 size_t 的 C++ 等价物。正如布赖恩所指出的,std:: 被用作命名空间以避免设置不适合所有人的全局变量。它就像 std::string 一样,也可以在根命名空间中定义。

于 2008-10-26T02:18:27.130 回答
4
std::size_t n = sizeof( long );

实际上,您还没有问过上面的具体做法是什么。使用 size_t,使用 std 命名空间进行限定,...

正如 C++ 标准所说(18.1), size_t 是标准 header 中定义的类型。我建议放弃关于可能从 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)。AC ++ 翻译单元 (2.1) 通过包含适当的标准库头 (16.2) 来获得对这些名称的访问。

size_t 是在 std 命名空间中定义的名称,因此在这种情况下,使用此名称的每个程序都应包含相应的标头。

接下来,3.7.3章节说:

However, referring to std, std::bad_alloc, and std::size_t is ill-formed unless the name has been declared by including the appropriate header.

Given that, program using size_t but not including header is ill-formed.

于 2009-08-06T10:23:48.810 回答
2

有时其他库会定义自己的 size_t。例如升压。std::size_t 指定您肯定想要 c++ 标准。

size_t 是一个 c++ 标准类型,它在命名空间 std 中定义。

于 2008-10-26T01:57:14.020 回答
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>

命名空间标准{

  使用 ::ptrdiff_t;
  使用 ::size_t;

}

我认为这应该说清楚。只要您包含 <cstddef> ,您就可以使用 size_t 或 std::size_t 因为 size_t 在 std 命名空间之外进行了类型定义,然后被包含在内。实际上你有

typedef long int ptrdiff_t;
typedef unsigned long int size_t;

命名空间标准{

  使用 ::ptrdiff_t;
  使用 ::size_t;

}
于 2009-04-16T04:30:09.183 回答
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会在你将使用的源文件中使用 while std::size_t。所以他们一定是兼容的,对吧?否则你会得到一个编译器错误。

/迈克尔·S。

于 2009-05-11T22:48:22.393 回答