Массивы не могут быть надежно динамически измерены, поскольку стандарт C ++ требует, чтобы размер всех массивов был известен при компиляции программы. Некоторые компиляторы допускают использование динамически изменяемых массивов в качестве расширения, но, поскольку все вещи нестандартны, на поддержку нельзя рассчитывать. Лучше избегать массивов переменной длины, если только по причине переносимости. И есть много других причин ( обсуждение здесь ).
Следующий неприятный момент заключается в том, что при передаче массива все измерения, кроме первого, должны быть известны во время компиляции. Это делает невозможным пропуск динамического размера двухмерного массива, если компилятор позволяет их создавать.
OK. Так что вы делаете вместо этого? Общее решение
std::vector<std::vector<int>> array_2d(x, std::vector<int>(y));
Затем вы передаете array_2d
по ссылке, чтобы минимизировать копирование
void rndArrayMaxNumber (std::vector<std::vector<int>> & array_2d)
Нет необходимости пропускать x
и y
. vector
знает, насколько она велика.
Это просто и в значительной степени самообеспечение. Это, наверное, все, что вам нужно. Скорее всего, вы не будете задавать этот вопрос или читать этот ответ, если пишете высокопроизводительный код.
Тем не менее, у него есть некоторые недостатки в производительности, поскольку один vector
гарантированно является непрерывным блоком памяти, а vector
из vector
s - нет. Это обрекает программу на погоню за указателями в памяти и склонность к плохому поведению в кэшировании. Каждый раз, когда программе приходится покидать процессор и высокоскоростной кэш, чтобы извлечь данные из ОЗУ (или, не дай бог, файл подкачки), вы оставляете среду, работающую в нескольких гигагерцах, за одну, работающую в сотнях мегагерц или хуже.
Подробнее о том, как это неприятно, можно получить здесь: https://blog.codinghorror.com/the-infinite-space-between-words/
Плюс каждое распределение имеет свои затраты. Одно большое выделение может стоить намного меньше, чем 1 vector
размера x
и x
vector
размера y
.
В связи с этим я рекомендую простой матричный класс, основанный на одном vector
.
#include <iostream>
#include <vector>
// template because if you are going to write this, why restrict yourself to just int?
template<class TYPE>
class Matrix
{
private:
// good to know how big you are
size_t rows, columns;
// and the vector containing the data
std::vector<TYPE> matrix;
public:
Matrix(size_t numrows, size_t numcols) :
rows(numrows), // remember the size
columns(numcols),
matrix(rows * columns) // and allocate storage
{
}
// does the same thing as the other constructor, except it sets a default value
Matrix(size_t numrows, size_t numcols, TYPE init) :
rows(numrows), columns(numcols), matrix(rows * columns, init)
{
}
// gets the value at row, column and allows it to be modified
TYPE & operator()(size_t row, size_t column)
{
// check bounds here if you want
// note the indexing math mapping 2 dimensions into 1
return matrix[row * columns + column];
}
// gets a copy of the the value at row, column
TYPE operator()(size_t row, size_t column) const
{
return matrix[row * columns + column];
}
// obvious what the next two methods do
size_t getRows() const
{
return rows;
}
size_t getColumns() const
{
return columns;
}
};
// handy dandy output helper.
friend std::ostream & operator<<(std::ostream & out, const Matrix & in)
{
for (int i = 0; i < in.getRows(); i++)
{
for (int j = 0; j < in.getColumns(); j++)
{
out << in(i, j) << ' ';
}
out << '\n';
}
return out;
}
Обратите внимание, что этот ответ вообще не вводит new
в уравнение.
Если вы хотите пойти по маршруту, вам нужно сделать гораздо больше работы. Как объявить 2d-массив в C ++, используя new? поможет вам начать этот путь, но, опять же, вам лучше обернуть один массив, как здесь: Как создать оператор индекса для класса Matrix?
Обратите особое внимание на невыполненный конструктор копирования и оператор присваивания. Это волшебный соус для создания хорошего матричного класса вокруг динамического массива, и по причинам, которые я могу отнести только к садизму, они исключены из этого примера. Прочитайте Что такое правило трех? для получения информации о том, зачем они нужны. Стоит прочитать ссылку «Правило трех», даже если вы используете vector
, потому что вы не можете написать нетривиальный C ++ без твердого контроля над правилом трех ( и его друзьями Five и Zero ).
Документация по std::vector