После некоторых проб и ошибок я нашел способ malloc 2D-массив, чтобы он был непрерывным в памяти, что эквивалентно нединамическому случаю.
int numRows =2;
int numCols = 4;
int (*p)[numCols];
p = (int (*)[numCols]) malloc(sizeof(int)*numRows*numCols);
Таким образом, p теперь в основном такой же, как если бы я сделал int p [2] [4] - за исключением его в куче вместо стека.
2 Вопросы:
Я пытался
p = new (int (*)[4])[2];
Но это дало ошибку:
error: cannot convert int (**)[4] to int (*)[4] in assignment
Здесь шаблон класса, который использует один std::vector
для хранения смежного буфера и объектов с прокси-серверами с размерами для доступа к элементам массива измерения по размеру:
template<typename T>
class TwoDArray {
private:
std::size_t n_rows;
std::size_t n_cols;
std::vector<T> buf;
public:
class OneDArrayProxy {
private:
T *rowptr;
std::size_t colsize;
public:
OneDArrayProxy(const T *rp, std::size_t cs) : rowptr(const_cast<T *>(rp)), colsize(cs) {}
T const &operator[](std::size_t index) const {
return rowptr[index];
}
T &operator[](std::size_t index) {
return rowptr[index];
}
std::size_t size() const { return colsize; }
};
TwoDArray(std::size_t rows, std::size_t cols) : n_rows(rows), n_cols(cols), buf(rows * cols) {}
TwoDArray() : TwoDArray(0, 0) {}
OneDArrayProxy operator[](std::size_t index) const {
return OneDArrayProxy(&buf[index * n_cols], n_cols);
}
std::size_t rows() const { return n_rows; }
std::size_t columns() const { return n_cols; }
};
Пример использования:
int main()
{
TwoDArray<int> arr(9, 5);
for (std::size_t i = 0; i < arr.rows(); i++) {
for (std::size_t j = 0; j < arr.columns(); j++) {
arr[i][j] = i * 10 + j;
}
}
for (std::size_t i = 0; i < arr.rows(); i++) {
// you can use the array element 'size()' function instead of 'columns()'
for (std::size_t j = 0; j < arr[i].size(); j++) {
std::cout << arr[i][j] << " ";
}
std::cout << std::endl;
}
}
1) Да, вы могли бы просто позвонить free()
Но обратите внимание, что вы выполняете сглаживание указателей (2 указателя на разные типы, int и int [] с тем же адресом), что может вызвать тонкие ошибки оптимизации. И в C++ очень плохая практика использования malloc()
, а numcols должны быть const
.
2) Способ, которым вы можете это сделать в C++, будет использовать [<array>][2]
если размер будет известен во время компиляции:
array<array<int, 4>,2> a;
Более гибкой альтернативой является использование векторов, которые обеспечивают динамический размер и изменение размера:
vector <vector <int>> b(2, vector<int>(4));
3) С новым вы также можете сделать:
p = new (int[2][4]);
Первое измерение также может быть переменным, но второе должно быть константой. Но я бы посоветовал вам использовать одну из стандартных альтернативных альтернатив.
Вы не можете сделать это в C++. Ваш код malloc()
отлично действует C, но недействителен C++. И это не сработает с new
.
C++ требует, чтобы типы массивов имели постоянный размер, C допускает типы массивов динамического размера. Существует только исключение для 1D массивов, которые могут быть выделены динамическим размером в C++, но это. В 2D-массиве второй размер должен быть известен во время компиляции.
Это тот момент, когда C намного сильнее, чем C++.
Требуется немного, чтобы убедить g++
следовать стандарту в этом отношении, но составление этой небольшой программы
#include <stdlib.h>
int main(int argc, char** args) {
int (*foo)[argc];
}
с g++ -pedantic -std=C++11 foo.cpp
добросовестно выдает сообщение об ошибке:
foo.cpp: In function ‘int main(int, char**):
foo.cpp:4:17: warning: ISO C++ forbids variable length array ‘foo [-Wvla]
malloc()
. malloc()
прекрасно доступна на обоих языках, но тип int (*)[some dynamic size]
не существует в C ++. Смотрите мое редактирование.
malloc
и даже неnew
2D - массив, использоватьvector<vector<int>>
malloc()
. В самом деле. Тогда не используйтеnew
тоже. Сделайтеvector<int> v(numRows * numCols)
, инкапсулируйте его в класс,operator[]
перегрузкиoperator[]
который возвращает прокси-объект, имеющий указатель (или что-то еще) на соответствующую строку внутри вектора, перегрузите егоoperator[]
как ну и тд