`sizeof` *真的*计算为`std :: size_t`吗? 它可以?
采取以下标准通道:
[C++11: 5.3.3/6]:
sizeof
和sizeof...
的结果是std::size_t
types的常量。 [注:std::size_t
是在标准头文件<cstddef>
(18.2)中定义的。 – 注意]
现在:
[C++11: 18.2/6]:
typessize_t
是一个实现定义的无符号整数types,它足够大以包含任何对象的字节大小。
当然,这段文字并不要求size_t
是一个用typedef
定义的types别名,但是由于它明确声明是由标准头文件<cstddef>
,所以我认为我们可以认为没有包含<cstddef>
删除任何保证size_t
应可用于程序。
但是,根据第一个引用,我们可以不pipe获取std::size_t
types的expression式。
我们实际上可以certificate这两个事实 :
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
parsing为“相同的types”,而不是 std::size_t
本身呢?
当然,如果std::size_t
是一个types别名,那么这两个是一样的,但是,再次,实际上这是不需要的。
不要混淆地图的领土。
types可以用types名来命名。 这些types名称可以是内置的,它们可以是用户定义的types,或者甚至可以是template
参数,并根据实例化引用多种不同的types。
但是名字不是那种types。 显然,标准并不要求所有types都有名字,典型的struct {}
是一个没有名字的types。
std::size_t
是一个typename。 它命名sizeof(expression)
返回的types。
编译器可以有一个types的规范名称 – __size_t
将是一个唯一的内置规范types名称的方法。
在该子句中,标准保证不pipesizeof(expression)
的types是什么,一旦你包含了#include <cstddef>
,名字std::size_t
现在就是指那个types。
在标准中,它们是指名称的types。 他们不会说“这个types名称所指的types”,而只是说“types$ NAME $”。 如果需要,编译器可以决定int
是__int_32_fast
另一个名字,标准也不会有任何异议。
同样的事情发生在std::nullptr_t
和std::initializer_list<Ts>
和std::type_info
:这些types的variables的使用并不总是要求为你提供这些types名称的头文件包含在你的程序中。
传统的C / C ++内置types都具有不需要头的规范名称。 缺点是这会破坏现有代码,因为全局范围中的新types名称与其他标识符相冲突。
通过使用“无名types”,可以通过包含头文件来获取名称,我们可以避免这个问题。
该标准只是要求sizeof(expr)
的types与std::size_t
是相同的types。 没有要求使用sizeof(expr)
使名称std::size_t
可用,并且因为std::size_t
只是命名内置整型types之一,所以没有任何问题。
据我所知,这个标准的段落需要下面的expression式:
typeid(sizeof(0)) == typeid(std::size_t)
将永远产生true
。 如果使用实际标识符std::size_t
, ::size_t
或任何其他别名/ typedef将是不相关的,只要按照std::typeinfo::operator==()
保留types的标识。
语言的其他地方出现同一types身份问题。 例如,在我的64位机器中,以下代码由于函数重定义而无法编译:
#include <cstddef> void foo(std::size_t x) {} void foo(unsigned long x) {}
是。
由sizeof
产生的sizeof
是一些无符号的整数types; 该实现定义了它是哪一个。
例如,在某些特定的实现中, sizeof
expression式的types可能是unsigned long
。
std::size_t
,如果它是一个typedef
,只不过是unsigned long
的替代名称。 所以这两个陈述:
sizeof ...
的types是一个unsigned long
types的常量
和
sizeof ...
的types是std::size_t
types的常量
对于这个实现来说,完全一样。 unsigned long
types和std::size_t
types是相同的types。 不同之处在于后者对于所有(符合)实现都是准确的,其中std::size_t
可能是unsigned int
或其他一些无符号types的别名。
就编译器而言, sizeof
产生unsigned long
types的结果; 编译器(而不是运行时库)不需要知道名称size_t
。
这一切都假定std::size_t
(或只是size_t
如果你在谈论C)是一个typedef。 这不是在C或C ++标准中阐明的。 尽pipe如此,通过将size_t
为typedef,实现可以直接符合标准的要求。 我不相信有任何其他便携式的方式来满足这些要求。 (它不能是一个macros或一个实现定义的关键字,因为这会侵犯用户的名字空间,并且一个macros不会在std
名字空间范围内)。编译器可以使size_t
实现特定的结构,而不是一个typedef,但是由于typedef工作得很好,这样做没有意义。 这将是很好,恕我直言,如果标准规定size_t
是一个typedef。
(一个不相干的问题:真正的问题是标准把结果称为“常量”,在ISO C中,“常数”是一个标记,比如一个整数字面量。据我所知,C ++不会“定义名词“常量”,但它确实引用了ISO C的定义, sizeof ...
是一个常量expression式 ;它不是一个常量 ,调用结果“常量值”是合理的。
这是相同的types,但你必须包括该头来使用它。