Раньше я думал, что ответ на этот вопрос "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
).
Это то, что параграф 5.3.4/1 стандарта С++ 11 указывает на результат выражения new
:
[...] Объекты, созданные новым выражением, имеют динамическую продолжительность хранения (3.7.4). [Примечание: время жизни таких сущность не обязательно ограничивается областью, в которой она создана. -end note] Если объект не является массивом object, новое выражение возвращает указатель на созданный объект. Если это массив, новое выражение возвращает указатель на исходный элемент массива.
Раньше я думал, что в С++ тип всех объектов определяется во время компиляции, но приведенный выше пример, похоже, опровергает эту веру. Кроме того, в пункте 1.8/1:
[...] Свойства объекта определяются , когда объект создается. Объект может иметь имя (раздел 3). Объект имеет продолжительность хранения (3.7), которая влияет на его время жизни (3.8). Объект имеет тип (3.9). [...]
Итак, мои вопросы:
- Что подразумевается под "свойствами" в последнем цитируемом абзаце? Очевидно, что имя объекта не может считаться чем-то, что определено "когда объект создан" - если "созданный" здесь не означает нечто иное, чем я думаю;
- Существуют ли другие примеры объектов, тип которых определяется только во время выполнения?
- Насколько корректно говорить, что С++ - это статически типизированный язык? Вернее, что является самым правильным способом классификации С++ в этом отношении?
Было бы здорово, если бы кто-нибудь мог разработать хотя бы один из вышеуказанных пунктов.
EDIT:
Стандарт, похоже, дает понять, что выражение new
действительно создает объект массива, а не только несколько объектов, выложенных как массив, как указано некоторыми. В пункте 5.3.4/5 (любезно предоставлено Xeo):
Когда выделенным объектом является массив (т.е. используется синтаксис noptr-new-declarator или идентификатор нового типа или type-id обозначает тип массива), новое выражение дает указатель на исходный элемент (если есть) массива. [Примечание: оба
new int
иnew int[10]
имеют типint*
, а типnew int[i][10]
-int (*)[10]
-end note] Атрибут-specifier-seq в noptr-new-declarator содержит для связанного типа массива.