Блог пользователя Bebronesy

Автор Bebronesy, история, 10 часов назад, По-русски

Всем привет, столкнулся со следующей проблемой: когда я создаю двумерный массив вида int a[n][n], Visual Studio 2022 выдаёт ошибку компиляции: "выражение не является константой", где выражение это n (n я предварительно ввожу через cin>>n;). Как можно решить данную проблему? Было бы славно решить её созданием двумерного вектора через библиотеку , так как привычно работать именно через неё.

  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

»
10 часов назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Машина тебе правильно говорит, $$$n$$$ не является константой.

  • »
    »
    9 часов назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Я понимаю, а как тогда создать двумерный массив размера n*m, где n и m вводятся? Приходится задачи на двумерные массивы писать в онлайн компиляторах потому что они не жалуются на такое

    • »
      »
      »
      5 часов назад, # ^ |
        Проголосовать: нравится +13 Проголосовать: не нравится

      Возможность объявлять массивы динамического размера называется VLA (variable length array) и является очень спорной возможностью языка C из стандарта C99. Она не входит в стандарт C++, однако некоторые компиляторы типа GCC включают в себя расширения, которые позволяют пользоваться ею и в С++. Именно поэтому на онлайн компиляторах, где зачастую по умолчанию предлагается GCC, такой код работает, а вот в VisualStudio c компилятором MSVC — нет.

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

      StackOverflow: Почему VLA не входит в стандарт С++?

      Как с этим жить?

      Если максимальное $$$N$$$ известно заранее, то можно создать массив достаточно большого размера, чтобы любое меньшее $$$N$$$ гарантированно в него помещалось.

      const int MAX_N = 1000;
      int a[MAX_N][MAX_N];
      

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

      int n, m;
      vector<vector<int>> vec(n, vector<int>(m, 0));
      

      чтобы память была одним последовательным куском можно использовать vector на n*m элементов и использовать индексы вида i*m + j. Чтобы это не резало глаза, можно написать функцию обертку, оформить 2D массив как класс с перегрузкой операторов или использовать std::mdspan

      • »
        »
        »
        »
        5 часов назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Добавлю, что можно не писать вектор-вектор-вектор-вектор-тип-тип, компилятор может сам это вывести:

        int n, m;
        cin >> n >> m;
        vector ints(n, 0);
        vector dp(n, vector(m, 0));
        

        Для одно- и двумерного вектора это не сильно увеличивает удобность, но для трёхмерного случая уже заметно:

        vector v0(n, vector(m, vector(k, 0LL)));
        vector v1(n, vector(m, vector<pair<int, int>>(k)));
        vector<vector<vector<pair<int, int>>>> v2(n, vector(m, vector<pair<int, int>>(k)));
        
        
      • »
        »
        »
        »
        67 минут назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Спасибо