【发布时间】:2013-04-03 00:23:21
【问题描述】:
我曾经认为这个问题的答案是“100%”,但最近有人指出了一个值得三思的例子。考虑一个声明为具有自动存储持续时间的对象的 C 数组:
int main()
{
int foo[42] = { 0 };
}
这里,foo 的类型显然是int[42]。相反,考虑这种情况:
int main()
{
int* foo = new int[rand() % 42];
delete[] foo;
}
这里,foo 的类型是int*,但是如何在编译时知道由new 表达式创建的对象的类型? (强调是为了强调我不是在谈论 new 表达式返回的指针,而是在谈论 new 表达式创建的 array 对象。
这是 C++11 标准的第 5.3.4/1 段对new 表达式结果的规定:
[...] new-expression 创建的实体具有动态存储持续时间 (3.7.4)。 [注:此类的生命周期 实体不一定限于创建它的范围。 —尾注] 如果实体是非数组 对象,new-expression 返回一个指向所创建对象的指针。如果是数组,new-expression 返回指向数组初始元素的指针。
我曾经认为在 C++ 中所有对象的类型都是在编译时确定的,但上面的例子似乎反驳了这种看法。此外,根据第 1.8/1 段:
[...] 对象的属性是由对象确定的 已创建。一个对象可以有一个名称(第 3 条)。一个对象有一个存储持续时间(3.7),它影响 它的寿命(3.8)。一个对象有一个类型(3.9)。 [...]
所以我的问题是:
- 最后引用段落中的“属性”是什么意思?显然,对象的名称不能算作是“创建对象时”确定的东西——除非“创建”这里的意思与我想的不同;李>
- 是否还有其他类型仅在运行时确定的对象示例?
- 说 C++ 是一种静态类型语言在多大程度上是正确的?或者更确切地说,在这方面对 C++ 进行分类的最恰当方法是什么?
如果有人能详细说明以上几点,那就太好了。
编辑:
标准似乎清楚地表明new 表达式确实创建了一个数组对象,而不仅仅是一些人指出的以数组形式排列的几个对象。根据第 5.3.4/5 段(Xeo 提供):
分配对象为数组时(即使用noptr-new-declarator语法或new-type-id 或 type-id 表示数组类型),new-expression 产生一个指向数组初始元素(如果有)的指针。 [注:
new int和new int[10]都有int*类型,new int[i][10]的类型是int (*)[10]—end note ] noptr-new-declarator 中的 attribute-specifier-seq 属于 关联的数组类型。
【问题讨论】:
-
我认为您混淆了
dynamic和static。无论rand()返回多少索引,您的示例都将返回int*..。那是动态内存分配……不是动态类型。 -
我几乎可以称之为“类型擦除”
-
使用 C 风格的数组来探测 C++ 类型系统会导致精神错乱。它们具有从 C 继承而来的相当古怪的属性,不能很好地适应严格的类型系统。所以答案是“那又怎样?”。
-
字符串文字(在 C++11 之前)也很古怪,除了它们从数组中得到的怪癖之外。字符文字也有一些怪癖。为了理解类型系统,它们是分散注意力的,而不是完全集成的部分。这就是为什么我说“那又怎样”;我觉得它们非常无趣。它们就是它们,它们不适合一个理性的系统。
-
你知道吗?这是进入 Stroustrup 官方 C++ 常见问题的绝佳候选者。
标签: c++ c++11 language-lawyer static-typing dynamic-typing