В C++ я бы хотел сделать что-то вроде:
int n = get_int_from_user();
char* matrix = new char[n][n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
delete [][] matrix;
но, конечно, это не работает. Как лучше всего сделать что-то подобное? Я видел несколько решений этой проблемы, но они кажутся довольно запутанными.





Для истинного двумерного массива:
int n = get_int_from_user();
char** matrix = new char*[n];
for (int i = 0; i < n; i++) {
matrix[i] = new char[n];
}
// Operations on matrix.
for (int i = 0; i < n; i++) {
delete [] matrix[i];
}
delete matrix;
Просто с головы до ног. Ошибки, без сомнения. Однако я думаю, что другие люди опубликовали более элегантный подход.
Обычно я делаю что-то вроде этого:
char *matrix = new char [width * height];
matrix[i + j * width] = 'c'; // same as matrix[i][j] = 'c';
delete [] matrix;
Да, это, наверное, лучший способ. Оберните доступ в функцию, и все будет хорошо.
Я считаю, что именно так и обрабатываются многомерные массивы под крышками
Ручной динамический способ:
Допустим, вам нужен массив шириной * высотой, наиболее эффективный способ - просто использовать одномерный массив:
char *matrix = new char[width*height];
Чтобы удалить его:
delete[] matrix;
Чтобы получить к нему доступ:
char getArrayValue(char *matrix, int row, int col)
{
return matrix[row + col*width];
}
Чтобы изменить это:
void setArrayValue(char *matrix, int row, int col, char val)
{
matrix[row + col*width] = val;
}
Матрица усиления:
Рассмотрите возможность использования boost :: matrix, если у вас может быть зависимость.
Затем вы можете подключиться к библиотекам улучшить линейную алгебру.
Вот какой-то пример кода boost :: matrix:
#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric::ublas;
matrix<char> m (3, 3);
for (unsigned i = 0; i < m.size1 (); ++ i)
for (unsigned j = 0; j < m.size2 (); ++ j)
m (i, j) = 3 * i + j;
В стеке для некоторых компиляторов:
Некоторые компиляторы фактически позволяют создавать в стеке массивы с размерами, определяемыми во время выполнения. g ++ - пример такого компилятора. Однако вы не можете сделать это по умолчанию VC++.
Итак, в g ++ это действительный код:
int width = 10;
int height = 10;
int matrix[width][height];
Дрю Холл упомянул, что эта функция C99 называется массивами переменной длины (VLA) и, вероятно, может быть включена в любом современном компиляторе.
См. Заголовок вопроса «... с размером, определенным во время выполнения». Поэтому он не может использовать стек или константу.
Вы можете создавать массивы с определенным размером в стеке в g ++
Это функция C99, называемая массивами переменной длины (VLA) - ее, вероятно, можно включить в любом современном компиляторе, поддерживающем C и C++.
Кажется, вам не хватает всего C++ (C с классами) :-). Это тот вид использования, который требует от класса его реализации.
Вы мог просто используете STL или другую стороннюю библиотеку классов, которая, я уверен, будет иметь структуру данных, которую вы ищете, но, если вам нужно свернуть свою собственную, просто создайте класс со следующими свойствами.
А как насчет std::vector< std::vector<int> > array2d;?
Стоит отметить тактико-технические характеристики. Изменение размера массива в одном направлении будет быстрым. Но доступ к элементам будет медленным из-за плохой локализации кеша (векторы могут оказаться в удаленных частях памяти). С другой стороны, если бы вы использовали непрерывное хранилище, как в большинстве других ответов, у вас было бы немного более медленное изменение размера по вертикали, немного более быстрое изменение размера по горизонтали и гораздо лучшая локализация кеша.
Мне нравится подход с одномерным массивом (выбранный ответ Брайана Р. Бонди) с расширением, в котором вы обертываете элементы данных в класс, чтобы вам не нужно было отслеживать ширину отдельно:
class Matrix
{
int width;
int height;
char* data;
public:
Matrix();
Matrix(int width, int height);
~Matrix();
char getArrayValue(int row, int col);
void setArrayValue(int row, int col, char val);
}
Реализация - это упражнение для читателя. ;)
Два возможных улучшения. Вы можете сделать его классом-шаблоном. И вы можете заменить getArrayValue и setArrayValue на operator () (int, int), возвращающий ссылку. Или, в идеале, эмуляция синтаксиса [x] [y] через прокси-класс, но я думаю, что сложно гарантировать, что прокси-класс всегда оптимизирован.
Думаю, это было бы неплохо.
int n = get_int_from_user();
char **matrix=new (char*)[n];
for(int i=0;i<n;i++)
matrix[i]=new char[n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
for(int i=0;i<n;i++)
delete []matrix;
delete []matrix;
std::vector<int> m;
Затем вызовите m.resize () во время выполнения.
int* matrix = new int[w*h];
если вы хотите сделать что-то вроде исключения Гаусса, ваша матрица должна быть
int** matrix = new int*[h];
for(size_t i(0); i < h; ++i)
matrix[i] = new int[w];
(при исключении Гаусса нам обычно нужно обменивать одну строку на другую, поэтому лучше поменять местами указатели на строки за постоянное время, чем переставлять путем копирования за линейное время).