我曾经认为这个问题的答案是“ 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
)。
这是 C++11 标准的第 5.3.4/1 段对new
表达式结果的规定:
[...] 由new-expression创建的实体具有动态存储持续时间 (3.7.4)。[注意:此类实体的生命周期不一定限于创建它的范围。—尾注] 如果实体是非数组对象,则new 表达式返回指向所创建对象的指针。如果它是一个数组,则new 表达式 返回一个指向数组初始元素的指针。
我曾经认为在 C++ 中,所有对象的类型都是在编译时确定的,但上面的例子似乎反驳了这种看法。此外,根据第 1.8/1 段:
[...] 对象的属性是在创建对象时确定的。一个对象可以有一个名称(第 3 条)。对象具有影响其生命周期 (3.8) 的存储持续时间 (3.7)。一个对象有一个类型(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中的属性说明符序列属于关联的数组类型。