I used to think that the answer to this question was "100%", but I've recently been pointed to an example that makes it worth thinking twice. Consider a C array declared as an object with automatic storage duration:
int main()
{
int foo[42] = { 0 };
}
Here, the type of foo
is clearly int[42]
. Consider, instead, this case:
int main()
{
int* foo = new int[rand() % 42];
delete[] foo;
}
Here, the type of foo
is int*
, but how can one tell the type of the object created by the new
expression at compile-time? (Emphasis is meant to stress the fact that I am not talking about the pointer returned by the new
expression, but rather about the array object created by the new
expression).
This is what Paragraph 5.3.4/1 of the C++11 Standard specifies about the result of a new
expression:
[...] Entities created by a new-expression have dynamic storage duration (3.7.4). [ Note: the lifetime of such an entity is not necessarily restricted to the scope in which it is created. —end note ] If the entity is a non-array object, the new-expression returns a pointer to the object created. If it is an array, the new-expression returns a pointer to the initial element of the array.
I used to think that in C++ the type of all objects is determined at compile-time, but the above example seems to disprove that belief. Also, per Paragraph 1.8/1:
[...] The properties of an object are determined when the object is created. An object can have a name (Clause 3). An object has a storage duration (3.7) which influences its lifetime (3.8). An object has a type (3.9). [...]
So my questions are:
- What is meant by "properties" in the last quoted paragraph? Clearly, the name of an object cannot count as something which is determined "when the object is created"- unless "created" here means something different than I think;
- Are there other examples of objects whose type is determined only at run-time?
- To what extent is it correct to say that C++ is a statically-typed language? Or rather, what is the most proper way of classifying C++ in this respect?
It would be great if anybody could elaborate at least on one of the above points.
EDIT:
The Standard seems to make it clear that the new
expression does indeed create an array object, and not just several objects laid out as an array as pointed out by some. Per Paragraph 5.3.4/5 (courtesy of Xeo):
When the allocated object is an array (that is, the noptr-new-declarator syntax is used or the new-type-id or type-id denotes an array type), the new-expression yields a pointer to the initial element (if any) of the array. [ Note: both
new int
andnew int[10]
have typeint*
and the type ofnew int[i][10]
isint (*)[10]
—end note ] The attribute-specifier-seq in a noptr-new-declarator appertains to the associated array type.
dynamic
and astatic
. Your example will return anint*
.. regardless of how many indicesrand()
returns. That's dynamic memory allocation.. not dynamic typing. – Yokum