Портирование включает в себя больше, чем просто работу, построчно, поэтому:
C:
double (*g2)[h][w] = malloc(h * w * sizeof(double));
...
g2[y][x] = ...;
C ++:
std::vector<double> g2(h*w);
...
g2[y+x*h] = ...; // or
g2[y*w+x] = ...;
Использование этого синтаксисанеудобен для доступа к элементам, поэтому вы можете захотеть обернуть его внутри простого класса.Пример:
#include <iostream>
#include <iterator>
#include <vector>
class arr2d {
public:
arr2d(size_t h, size_t w) : data_(h * w), w_(w) {}
inline double& operator()(size_t y, size_t x) {
return data_[y * w_ + x];
}
inline double operator()(size_t y, size_t x) const {
return data_[y * w_ + x];
}
// getting pointer to a row
inline double* operator[](size_t y) {
return &data_[y * w_];
}
inline double const* operator[](size_t y) const {
return &data_[y * w_];
}
inline size_t width() const { return w_; }
private:
std::vector<double> data_;
size_t w_;
};
int main() {
arr2d g2(3, 4);
g2(2, 3) = 3.14159;
// alternative access:
g2[1][2] = 1.23456;
std::cout << g2[2][3] << "\n";
double* row = g2[2];
std::copy(row, row + g2.width(), std::ostream_iterator<double>(std::cout, ", "));
std::cout << "\n";
}
Вывод:
3.14159
0, 0, 0, 3.14159,
Неинициализируемая версия может выглядеть следующим образом:
class arr2d {
public:
arr2d(size_t h, size_t w) : data_(new double[w * h]), w_(w) {}
inline double& operator()(size_t y, size_t x) { return data_[y * w_ + x]; }
inline double operator()(size_t y, size_t x) const { return data_[y * w_ + x]; }
inline double* operator[](size_t y) { return &data_[y * w_]; }
inline double const* operator[](size_t y) const { return &data_[y * w_]; }
inline size_t width() const { return w_; }
private:
std::unique_ptr<double[]> data_;
size_t w_;
};
Но обратите внимание, что
std::copy(row, row + g2.width(), std::ostream_iterator<double>(std::cout, ", "));
из первого примера приведет к неопределенному поведению.
Также обратите внимание, что в этой версии будут удалены конструктор копирования и оператор назначения копирования.Вы должны будете реализовать их самостоятельно, если они вам нужны.
Время создания для неинициализируемой версии, конечно, трудно превзойти с любой инициализирующей версией, но для времени доступа можно подумать, что поисктаблица, или косвенное указание, как вы ее называете, поскольку строки ускорят процесс по сравнению с умножением и сложением за один раз.
Мои результаты:
8x8
http://quick -benchCOM
Кажется, меняется.Версия для поиска быстрее для матрицы 4096x4096, но наивная версия быстрее для двух меньших.Вы должны сравнить, используя размеры, близкие к тому, что вы будете использовать, а также проверить с различными компиляторами.Иногда я получаю совершенно противоположные «победители» при смене компилятора.
Поскольку вы не возражаете против наследования от std::vector
или сохранения дополнительных данных для таблицы соответствия, это может быть вариантом.Кажется, он немного превосходит другие версии.
class arr2d : protected std::vector<double*> {
public:
using std::vector<double*>::operator[]; // "row" accessor from base class
arr2d(size_t h, size_t w) :
std::vector<double*>(h),
data_(new double[w * h]),
w_(w),
h_(h)
{
for(size_t y = 0; y < h; ++y)
(*this)[y] = &data_[y * w];
}
inline size_t width() const { return w_; }
inline size_t height() const { return h_; }
private:
std::unique_ptr<double[]> data_;
size_t w_, h_;
};
Вот собственные измерения Philipp-P (OP: s) для различных реализаций 2D-массива:
8x8
http://quick -bench.com / vMS6a9F_KrUf97acWltjV5CFhLY
1024x1024
http://quick -bench.com / A8a2UKyHaiGMCrf3uranwOCwmkA
4096x4096
* 1063ch1064646464XmYQc0kAUWU23V3Go0Lucioi_Rg
Результаты для 5-точечного кода трафарета для тех же версий:
8x8
http://quick -bench.com / in_ZQTbbhur0I4mu-NIquT4c0 * 1072 *1072* 1072 *1072* http://quick -bench.com / tULLumHZeCmC0HUSfED2K4nEGG8
4096x4096
http://quick -bench.com / _MRNRZ03Favx91-5IXnxGNpRNwQ