2013-09-21 4 views
3

Я пишу функцию для объединения блоков m x m в матрицу n x n. Блоки представляют собой 3d-указательный массив B[BlockIndex][BlockRow][BlockColumn], а матрица n x n представляет собой 2d-указательный массив M[Row][Column]. Если M - 4x4, а B - 4 матрицы 2x2, то BlockIndex = 0 - верхний левый блок, BlockIndex = 1 - верхний правый, BlockIndex = 2 - нижний левый, а BlockIndex = 3 - нижний правый.C++ Изменить адрес элемента массива

Я хотел бы просто указать элементы M в начало строк соответствующих блоков, но я не могу показаться (и не знаю, если это возможно) установить адрес элемента [i][j] M. Я могу установить M[i] на B[BlockIndex][i], так что (используя пример 2x2 и 4x4) первые 2 элемента i-й строки M указывают на i-ю строку блока BlockIndex-th, но как я могу указать третий элемент i-й строки из M в i-ю строку блока (BlockIndex + 1) -го блока?

Я понимаю, что я как бы противоречу идее смежной памяти здесь, поскольку я беру массив из 4 элементов (i-й строки М), которые существуют бок о бок в памяти и пытаются сломать это последовательность, указывая последние 2 элемента этого массива на другой массив из 2 элементов. Однако, если мне это удастся, это сэкономит время, когда матрицы станут огромными, так как я не хочу прибегать к глубокому копированию B в M по элементам. Я также понимаю, что я могу злоупотреблять «глубокой копией» здесь ...

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

Ниже приведено текущее воплощение функции, которую я пишу, для разделения/объединения матриц в/из меньших блоков.

Спасибо,

Tim

bool SplitCombineMat(double** &Mat, double*** &Blocks, int const& MatSize, 
           int const& BlockSize, bool const& SplitMatrix) 
{ 
    bool IsOk = true; 

    if (SplitMatrix) 
     IsOk = PrepareBlocks(Blocks, MatSize, BlockSize); 

    if (IsOk) 
    { 
     // Set the beginnings (pointers) of the rows of blocks 
     // to the right elements of Mat. 
     // This is a shallow copy. 
     int BlockIndex = 0; 
     for (int i = 0 ; i <= MatSize - BlockSize ; i += BlockSize) 
      for (int j = 0 ; j <= MatSize - BlockSize ; i += BlockSize){ 
       for (int k = 0 ; k < BlockSize ; k++) 
        if (SplitMatrix) 
         Blocks[BlockIndex][k] = &Mat[k+i][j]; 
        else // Here want to use pointers as above but can't figure it out... 
          // Something like -- &Mat[k+i][j] = Blocks[BlockIndex][k]; 
         for (int l = 0 ; l < BlockSize ; l++) 
          Mat[k+i][l] = Blocks[BlockIndex][k][l]; 
       BlockIndex++; 
      } 
    } 

    return IsOk; 
} 

ответ

2

То, что вы хотите сделать, это невозможно в C++. Как вы сказали, массив является смежной областью памяти, и вы не можете продолжить ее с другого адреса посередине.

Кроме того, вы не можете «изменить» адрес массива, это константа. Однако вы можете использовать массивы указателей, но в вашем случае это тоже не сработает. Единственный вариант - скопировать содержимое массивов.

Может быть некоторый нестандартный векторный класс, который позволяет вам это делать, но тогда ваш доступ к массивам будет медленным.

Я думаю, что просто копирование всего не должно быть слишком большой проблемой для производительности. Скорее всего, генерация начальных блоков (или их чтение) будет доминировать во время копирования. Приветствия.

+0

Спасибо. Я так много думал, но всегда можно надеяться на право? – twilsonco

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