c ++ массив - выражение должно иметь постоянное значение - PullRequest
41 голосов
/ 10 февраля 2012

Я получаю ошибку, когда пытаюсь создать массив из объявленных переменных.

int row = 8;
int col= 8;
int [row][col];

Почему я получаю эту ошибку:

выражение должно иметь постоянное значение.

Ответы [ 7 ]

46 голосов
/ 10 февраля 2012

При создании такого массива его размер должен быть постоянным. Если вам нужен массив динамического размера, вам нужно выделить для него память в куче, и вам также нужно будет освободить его с помощью delete, когда вы закончите:

//allocate the array
int** arr = new int*[row];
for(int i = 0; i < row; i++)
    arr[i] = new int[col];

// use the array

//deallocate the array
for(int i = 0; i < row; i++)
    delete[] arr[i];
delete[] arr;

Если вам нужен фиксированный размер, тогда он должен быть объявлен как const:

const int row = 8;
const int col = 8;
int arr[row][col];

Также

int [row][col];

даже не предоставляет имя переменной.

16 голосов
/ 10 февраля 2012

Стандарт требует, чтобы длина массива была значением, которое вычисляется во время компиляции, чтобы компилятор мог выделить достаточно места в стеке.В вашем случае вы пытаетесь установить для длины массива значение, которое неизвестно во время компиляции.Да, я знаю, что кажется очевидным, что это должно быть известно компилятору, но здесь это не так.Компилятор не может делать никаких предположений о содержании непостоянных переменных.Итак, перейдите с:

const int row = 8;
const int col= 8;
int a[row][col];

UPD: некоторые компиляторы на самом деле позволяют вам это осуществить.IIRC, g ++ имеет эту функцию.Однако никогда не используйте его, потому что ваш код станет непереносимым для компиляторов.

15 голосов
/ 10 февраля 2012

C ++ не допускает непостоянных значений для размера массива. Вот как это было задумано.

C99 допускает, чтобы размер массива был переменной, но я не уверен, что это разрешено для двух измерений. Некоторые компиляторы C ++ (gcc) допускают это как расширение, но вам может потребоваться включить опцию компилятора, чтобы разрешить это.

И я почти пропустил это - вам нужно объявить имя переменной, а не только размеры массива.

8 голосов
/ 05 февраля 2016

Вы можете использовать #define в качестве альтернативного решения, которое не вводит vector и malloc, и вы все еще используете тот же синтаксис при определении массива.

#define row 8
#define col 8

int main()
{
int array_name[row][col];
}
6 голосов
/ 10 февраля 2012

Когда вы объявляете переменную как здесь

int a[10][10];

вы говорите компилятору C ++, что вы хотите, чтобы 100 последовательных целых чисел выделялись в памяти программы во время выполнения. Затем компилятор предоставит вашей программе столько доступной памяти, и все будет хорошо с миром.

Если вы все же скажете компилятору

int x = 9001;
int y = 5;
int a[x][y];

компилятор не имеет возможности узнать, сколько памяти вам действительно понадобится во время выполнения, без проведения очень сложного анализа, чтобы отследить каждое последнее место, где значения x и y изменились [если есть]. Вместо того, чтобы поддерживать такие массивы переменного размера, C ++ и C настоятельно рекомендуют, если не прямо, требовать, чтобы вы использовали malloc () для ручного выделения нужного пространства.

TL; DR

int x = 5;
int y = 5;
int **a = malloc(x*sizeof(int*));
for(int i = 0; i < y; i++) {
    a[i] = malloc(sizeof(int*)*y);
}

a теперь является двумерным массивом размером 5x5 и будет вести себя так же, как int a [5] [5]. Поскольку вы выделили память вручную, C ++ и C требуют, чтобы вы также удалили ее вручную ...

for(int i = 0; i < x; i++) {
    free(a[i]); // delete the 2nd dimension array
}
free(a); // delete a itself
0 голосов
/ 10 марта 2019

Вы также можете использовать вектор фиксированной длины и обращаться к нему с помощью индексации, но это менее эффективно, чем использование указателей

int Lcs(string a, string b) 
{
    int x = a.size() + 1;
    int y = b.size() + 1;

    vector<vector<int>> L(x, vector<int>(y));

    for (int i = 1; i < x; i++)
    {
        for (int j = 1; j < y; j++)
        {
            L[i][j] = a[i - 1] == b[j - 1] ?
                L[i - 1][j - 1] + 1 :
                max(L[i - 1][j], L[i][j - 1]);
        }
    }

    return L[a.size()][b.size()];
}
0 голосов
/ 09 июня 2015

Нет, это не обязательно должно быть константой, причина, по которой его код неверен, заключается в том, что ему нужно включить имя переменной перед объявлением.

int row = 8;
int col= 8;
int x[row][col];

В Xcode, который будет компилироваться и запускаться без проблем, в компиляторе M $ C ++ в .NET он не будет компилироваться, он будет жаловаться, что вы не можете использовать неконстантный литерал для инициализации массива, размер должен быть известен в время компиляции

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...