Подтвердить что ты не робот

Константы и агрегаты С++ внутри тела функции по сравнению с внешним

Рассмотрим следующий фрагмент кода:

#include <iostream>
using namespace std;

int main()
{
    int x = 3;
    const int i[] = { 1, 2, 3, 4 };
    float f[i[3]]; 
    struct S { int i, j; };
    const S s[] = { { 1, 2 }, { 3, 4 } };
    double d[s[1].j];
}

Он работает без ошибок. Однако, следующее:

#include <iostream>
using namespace std;


int x = 3;
const int i[] = { 1, 2, 3, 4 };
float f[i[3]]; // error: array bound is not an integer constant before ']' token|
struct S { int i, j; };
const S s[] = { { 1, 2 }, { 3, 4 } };
double d[s[1].j]; // error: array bound is not an integer constant before ']' token|

int main()
{
    return 0;
}

Не получается, поскольку он получает ошибки, выделенные как комментарии. Может ли кто-нибудь объяснить мне, почему это?

4b9b3361

Ответ 1

Скорее всего, причина, по которой компилятор разрешает его в рамках функции, связан с расширением компилятора: массивами переменной длины. Они позволяют массивам, объявленным внутри функций, иметь длины, отличные от constexpr. Но он работает только внутри функций, а не в глобальном масштабе.

Ответ 2

Вы должны использовать constexpr вместо const

constexpr int i[] = { 1, 2, 3, 4 };
constexpr S s[] = { { 1, 2 }, { 3, 4 } };

const применяется для переменных и не позволяет им изменять ваш код.

constexpr сообщает компилятору, что это выражение показывает значение времени компиляции, поэтому его можно использовать в таких местах, как длина массива, присваивание константным переменным, и др.

Причина, почему он компилируется в funcion, - это VLA. Невозможно объявить VLA в глобальной области.

6.7.6.2 Объявление манифеста

2 Если идентификатор объявлен как имеющий измененный тип, он должен быть обычным идентификатором (как определено в 6.2.3), не имеют и имеют либо область видимости блока, либо область действия прототипа функции. Если идентификатор объявляется объектом со статикой или потоком времени хранения, он не должен иметь тип массива переменной длины.

Также VLA не входят в standard, его единственное расширение для компилятора здесь.