采取以下标准段落:
[C++11: 5.3.3/6]:
sizeof
和sizeof...
的结果是std::size_t
类型的常量。 [注意:std::size_t
在标准标题<cstddef>
(18.2)中定义。 -end note]
现在:
[C++11: 18.2/6]:
类型size_t
是一个实现定义的无符号整数类型,其大小足以包含任何对象的字节大小。
当然,该段落并不要求size_t
是使用typedef
定义的类型别名,但由于明确声明标准标题<cstddef>
可用,因此我认为我们可以理解为,如果不包含<cstddef>
,则应删除size_t
对程序可用的任何保证。
然而,根据第一个引用,我们可以获得std::size_t
类型的表达式。
We can actually demonstrate both of these facts:
int main()
{
typedef decltype(sizeof(0)) my_size_t;
my_size_t x = 0; // OK
std::size_t y = 1; // error: 'size_t' is not a member of 'std'
}
程序看不到 std::size_t
,但sizeof(0)
仍然给我们一个?真的?
因此5.3.3/6
有缺陷并且它实际上具有“与std::size_t
解析为的相同类型”是不正确的,但是不 std::size_t
本身?
当然,如果std::size_t
是一个类型别名,那么这两个是同一个,但同样,实际上并不需要它。
答案 0 :(得分:52)
标准只是要求sizeof(expr)
的类型与std::size_t
的类型相同。没有授权使用sizeof(expr)
使名称std::size_t
可用,并且由于std::size_t
只是命名其中一个内置整数类型,因此没有真正的问题。
答案 1 :(得分:46)
不要混淆地图的地图。
类型可以通过类型名称命名。这些类型名称可以是内置的,也可以是用户定义的类型,或者它们甚至可以是template
参数,并根据实例化引用多种不同的类型。
但名字不是类型。显然,标准并不要求所有类型都有名称 - 经典struct {}
是一种没有名称的类型。
std::size_t
是一个类型名称。它命名sizeof(expression)
返回的类型。
编译器可以具有该类型的规范名称 - __size_t
将是一种具有唯一内置规范类型名称的方式。
该条款中的标准保证,无论sizeof(expression)
的类型是什么,一旦#include <cstddef>
,名称std::size_t
现在引用该类型。
在标准中,它们按名称引用类型。他们没有说&#34;这个类型名称引用的类型&#34;,而只是说&#34;类型$ NAME $&#34;。如果需要,编译器可以决定int
是__int_32_fast
的另一个名称,标准也没有异议。
同样的事情发生在std::nullptr_t
和std::initializer_list<Ts>
以及std::type_info
上:使用这些类型的变量并不总是要求包含为这些类型提供名称的标题在你的程序中。
传统的C / C ++内置类型都具有不需要标头的规范名称。缺点是这会破坏现有代码,因为全局范围中的新类型名称会与其他标识符冲突。
通过使用&#34;无名类型&#34;,您可以通过包含头文件获取其名称,我们可以避免这个问题。
答案 2 :(得分:5)
据我了解,此标准段落需要以下表达式:
typeid(sizeof(0)) == typeid(std::size_t)
总是会产生true
。如果您使用实际标识符std::size_t
,::size_t
或任何其他别名/ typedef将无关紧要,只要保留类型的标识(根据std::typeinfo::operator==()
)。
相同的类型标识问题出现在该语言的其他位置。例如,在我的64位机器中,由于函数重新定义,以下代码无法编译:
#include <cstddef>
void foo(std::size_t x)
{}
void foo(unsigned long x)
{}
答案 3 :(得分:5)
是
sizeof
产生的类型是一些无符号整数类型;实现定义了它是哪一个。
例如,在某些特定实现中,sizeof
表达式的类型可能为unsigned long
。
std::size_t
,如果它是typedef
,只不过是unsigned long
的替代名称。所以这两个陈述:
类型的常量
sizeof ...
的类型是unsigned long
和
类型的常量
sizeof ...
的类型是std::size_t
对于该实现说的是完全相同的。类型unsigned long
和类型std::size_t
属于同一类型。不同之处在于后者对所有(符合标准)实现都是准确的,其中std::size_t
可能是unsigned int
或其他一些无符号类型的别名。
就编译器而言,sizeof
产生类型为unsigned long
的结果;编译器(与运行时库相对)不需要知道名称size_t
。
这一切都假设std::size_t
(或者只是size_t
,如果你在谈论C)是一个typedef。这在C或C ++标准中都没有说明。然而,通过使size_t
成为typedef,实现可以直接符合标准的要求。我不相信有任何其他便携式方式来满足这些要求。 (它不能是宏或实现定义的关键字,因为它会侵犯用户的名称空间,并且宏不会限定在std
命名空间内。)编译器可以 make size_t
除了typedef之外的一些特定于实现的构造,但由于typedef工作得非常好,所以没有必要这样做。如果标准声明size_t
是一个typedef,那将是很好的,恕我直言。
(一个无关紧要的旁边:真正的问题是标准将结果称为“常量”。在ISO C中,“常量”是一个标记,例如整数文字.C ++,据我所知,没有定义名词“常量”,但它确实引用了术语的ISO C定义。sizeof ...
是一个常量表达式;它不是常量。调用结果“常量值”是合理的。)
答案 4 :(得分:2)
它是相同的类型,但您必须包含该标头才能使用它。