2016-03-12 2 views
1

я наткнулся на этот бит кода (source):Trouble Понимание одного варианта выполнения динамического массива массивов

// memory allocation 
float *temp = new float[(order-1)*(order-1)]; 
float **minor = new float*[order-1]; 
for(int i=0;i<order-1;i++) 
    minor[i] = temp+(i*(order-1)); 

, и я действительно не понимаю. Что пытается сделать автор этого кода? (Да, я знаю, что он пытается сделать программу, чтобы найти обратную матрицу, но я не вижу, как работает этот бит кода.)

Я думаю, что это эквивалентно:

float **minor; 
minor = new float*[order-1]; 
for(int i=0;i<order-1;i++) 
    minor[i] = new float[(order-1)*(order-1)]; 

потому что +(i*(order-1)) кажется, что он только туда, чтобы двигаться вперед, что по существу является шириной ячейки памяти. Я уверен, что я не мог ошибаться в этой гипотезе. Несмотря на мою неправильную теорию, я не могу найти объяснения этому нигде, поэтому глубокое объяснение будет высоко оценено. Также было бы полезно пояснить, как реализовать это с вектором векторов поплавков.

+3

* Что автор этого кода пытается выполнить? * - Чтобы запутать читателя, и он, кажется, преуспевает :-). –

ответ

1

Первый код эффективно выделяет (порядок-1) x (порядок-1) матрицу. Его можно рассматривать как minor [i] [j]. Его также можно рассматривать линейно через temp: temp [i * (order-1) + j]. Иногда использование этих двух способов обращения к матрице может быть удобным. Многие коммерческие библиотеки с открытым исходным кодом работают с линейно адресованными матрицами.

Другой способ взглянуть на него: temp выделяется как большой блок, а затем второстепенный индексирует в temp для каждой строки (или столбца, в зависимости от вашей точки зрения).

Второй код не совпадает. Он выделяет (порядок-1) x (порядок-1) x (порядок-1) элементов.

+0

Вы могли бы добавить, что выделение его как одного массива вместо массива указателей на большее количество массивов является более удобным для кэширования и уменьшает фрагментацию кучи, что, вероятно, стало причиной этого. –

+0

Является ли второй код тем же, если 'minor [i] = new float [(order-1) * (order-1)];' заменяется на 'minor [i] = new float [order-1];'? – Larrimus

+0

Не для всех целей. Вы можете выиграть, пройдя через отладчик с относительно небольшим порядком, а затем увидите фактические адреса указателей. В первом коде, если порядок равен 5, то младший [0] может быть 0x1000, minor [1] = 0x1010 (спустя 16 байт, поскольку поплавок равен 4 байтам), minor [2] = 0x1020, minor [3] = 0x1030 , Если вы не хорошо читаете hex, просто поместите значения в десятичные числа. Во втором случае каждая младшая [] запись имеет 64 байта, номер для 16 поплавков. Даже с вашим новым комментарием меньшие [] значения будут разбросаны по памяти. Это может быть или не быть проблемой. –

Смежные вопросы