История изменений
Исправление quasimoto, (текущая версия) :
#include <array>
#include <cstdio>
template <typename T, size_t h, size_t w>
using Matrix = std::array<std::array<T, w>, h>;
struct Something {
bool property;
int value;
Something() : property(true) {}
};
template <size_t h, size_t w>
void doSomething(Matrix<Something, h, w>& mx)
{
int x = 0;
for (auto& col : mx)
for (auto& el : col) {
printf("%p\n", &el);
el.value = ++x;
}
}
int main()
{
printf("sizeof cell = %ld\n", sizeof(Something));
constexpr size_t h = 3, w = 3;
Matrix<Something, h, w> mx;
// movb $1, (%rsp)
// movb $1, 8(%rsp)
// movb $1, 16(%rsp)
// movb $1, 24(%rsp)
// movb $1, 32(%rsp)
// movb $1, 40(%rsp)
// movb $1, 48(%rsp)
// movb $1, 56(%rsp)
// movb $1, 64(%rsp)
doSomething(mx);
for (size_t i = 0; i < h; ++i) {
printf("{ ");
for (size_t j = 0; j < w; ++j)
printf("(%p){%d %d} ", &mx[i][j], mx[i][j].property, mx[i][j].value);
puts("}");
}
}
/*
sizeof cell = 8
0x7ff0000d8
0x7ff0000e0
0x7ff0000e8
0x7ff0000f0
0x7ff0000f8
0x7ff000100
0x7ff000108
0x7ff000110
0x7ff000118
{ (0x7ff0000d8){1 1} (0x7ff0000e0){1 2} (0x7ff0000e8){1 3} }
{ (0x7ff0000f0){1 4} (0x7ff0000f8){1 5} (0x7ff000100){1 6} }
{ (0x7ff000108){1 7} (0x7ff000110){1 8} (0x7ff000118){1 9} }
*/
/*
total heap usage: 0 allocs, 0 frees, 0 bytes allocated
*/
Обрати внимание на 0 аллокаций в куче, на код аллокации на стеке, на дефолтный конструктор, на два способа обхода и на непрерывный layout элементов матрицы в памяти.
Если h и w неизвестны на момент компиляции, то нужно делать как предложил tailgunner, то есть писать свой класс с аллокацией одним куском и доступом с помощью арифметики i * w + j индексов. На самом деле (по стандарту), для статических T[h][w] и std::array<std::array<T, w>, h> компилятор сам располагает их непрерывно в памяти и пишет ту же самую арифметику для индексов в ассемблер для [ i ][j].
Исходная версия quasimoto, :
#include <array>
#include <cstdio>
template <typename T, size_t h, size_t w>
using Matrix = std::array<std::array<T, w>, h>;
struct Something {
bool property;
int value;
Something() : property(true) {}
};
template <size_t h, size_t w>
void doSomething(Matrix<Something, h, w>& mx)
{
int x = 0;
for (auto& col : mx)
for (auto& el : col) {
printf("%p\n", &el);
el.value = ++x;
}
}
int main()
{
printf("sizeof cell = %ld\n", sizeof(Something));
constexpr size_t h = 3, w = 3;
Matrix<Something, h, w> mx;
// movb $1, (%rsp)
// movb $1, 8(%rsp)
// movb $1, 16(%rsp)
// movb $1, 24(%rsp)
// movb $1, 32(%rsp)
// movb $1, 40(%rsp)
// movb $1, 48(%rsp)
// movb $1, 56(%rsp)
// movb $1, 64(%rsp)
doSomething(mx);
for (size_t i = 0; i < h; ++i) {
printf("{ ");
for (size_t j = 0; j < w; ++j)
printf("(%p){%d %d} ", &mx[i][j], mx[i][j].property, mx[i][j].value);
puts("}");
}
}
/*
sizeof cell = 8
0x7ff0000d8
0x7ff0000e0
0x7ff0000e8
0x7ff0000f0
0x7ff0000f8
0x7ff000100
0x7ff000108
0x7ff000110
0x7ff000118
{ (0x7ff0000d8){1 1} (0x7ff0000e0){1 2} (0x7ff0000e8){1 3} }
{ (0x7ff0000f0){1 4} (0x7ff0000f8){1 5} (0x7ff000100){1 6} }
{ (0x7ff000108){1 7} (0x7ff000110){1 8} (0x7ff000118){1 9} }
*/
/*
total heap usage: 0 allocs, 0 frees, 0 bytes allocated
*/
Обрати внимание на 0 аллокаций в куче, на код аллокации на стеке, на дефолтный конструктор, на два способа обхода и на непрерывный layout элементов матрицы в памяти.
Если h и w неизвестны на момент компиляции, то нужно делать как предложил tailgunner, то есть писать свой класс с аллокацией одним куском и доступом с помощью арифметики i * w + j индексов. На самом деле (по стандарту), для статических T[h][w] и std::array<std::array<T, w>, h> компилятор сам располагает их непрерывно в памяти и пишет ту же самую арифметику для индексов в ассемблер для [j].