C ++ Избегание тройных указателей - PullRequest
0 голосов
/ 28 февраля 2019

Я пытаюсь создать массив X-указателей, ссылающихся на матрицы измерений Y на 16. Есть ли способ сделать это в C ++ без использования тройных указателей?

Редактировать: Добавление некоторыхконтекст для проблемы.

На экране имеется несколько геометрий, каждая с преобразованием, которое было сведено к массиву 1x16.Каждый снимок представляет преобразования для каждого из числа компонентов.Таким образом, размеры матрицы равны 16 по num_components по num_snapshots, где последние два измерения известны во время выполнения.В конце концов, у нас есть много геометрий с примененным движением.

Я создаю функцию, которая принимает аргумент тройного указателя, хотя я не могу использовать тройные указатели в моей ситуации.Какими еще способами я могу передать эти данные (возможно, с помощью нескольких аргументов)?В худшем случае я думал о сведении всей этой трехмерной матрицы в массив, хотя это кажется неаккуратным.Любые лучшие предложения?

Что у меня сейчас есть:

function(..., double ***snapshot_transforms, ...)

Чего я хочу достичь:

function (..., <1+ non-triple pointer parameters>, ...)

Ниже приведена не та функция, которую я создаю,принимает тройной указатель, но показывает, что это за данные.

static double ***snapshot_transforms_function (int num_snapshots, int num_geometries)
{
    double component_transform[16];

    double ***snapshot_transforms = new double**[num_snapshots];

    for (int i = 0; i < num_snapshots; i++)
    {
        snapshot_transforms[i] = new double*[num_geometries];

        for (int j = 0; j < num_geometries; j++)
        {
            snapshot_transforms[i][j] = new double[16];

            // 4x4 transform put into a 1x16 array with dummy values for each component for each snapshot
            for (int k = 0; k < 16; k++)
                snapshot_transforms[i][j][k] = k;
        }
    }

    return snapshot_transforms;
}

Edit2: Я не могу ни создавать новые классы, ни использовать такие функции C ++, как std, как открытыеПрототип функции в заголовочном файле помещается в оболочку (которая не знает, как интерпретировать тройные указатели) для перевода на другие языки.

Edit3: После каждого вводав комментариях я думаю, что использование плоского массива, вероятно, является лучшим решением.Я надеялся, что будет какой-то способ разделить этот тройной указатель и аккуратно организовать эти сложные данные по нескольким частям данных, используя простые типы данных, включая одиночные указатели.Хотя я не думаю, что есть хороший способ сделать это, учитывая мои предостережения здесь.Я ценю помощь каждого =)

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

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

#include <vector>
#include <memory>  // for shared_ptr (not strictly necessary, but used in main() to avoid unnecessarily copying of Matrix objects)

/** Represents a (numRows x numCols) 2D matrix of doubles */
class Matrix
{
public:
   // constructor
   Matrix(int numRows = 0, int numCols = 0)
      : _numRows(numRows)
      , _numCols(numCols)
   {
      _values.resize(_numRows*_numCols);
      std::fill(_values.begin(), _values.end(), 0.0f);
   }

   // copy constructor
   Matrix(const Matrix & rhs)
      : _numRows(rhs._numRows)
      , _numCols(rhs._numCols)
   {
      _values.resize(_numRows*_numCols);
      std::fill(_values.begin(), _values.end(), 0.0f);
   }

   /** Returns the value at (row/col) */
   double get(int row, int col) const {return _values[(row*_numCols)+col];}

   /** Sets the value at (row/col) to the specified value */
   double set(int row, int col, double val) {return _values[(row*_numCols)+col] = val;}

   /** Assignment operator */
   Matrix & operator = (const Matrix & rhs)
   {
      _numRows = rhs._numRows;
      _numCols = rhs._numCols;
      _values  = rhs._values;
      return *this;
   }

private:
   int _numRows;
   int _numCols;
   std::vector<double> _values;
};

int main(int, char **)
{
   const int numCols = 16;
   std::vector< std::shared_ptr<Matrix> > matrixList;
   for (int i=0; i<100; i++) matrixList.push_back(std::make_shared<Matrix>(i, numCols));

   return 0;
}
0 голосов
/ 28 февраля 2019

Проще, лучше и с меньшими ошибками использовать std::vector.Вы используете C ++, а не C в конце концов.Я заменил все указатели массива в стиле C на vector s.Typedef doublecube делает так, что вам не нужно вводить vector<vector<vector<double>>> снова и снова.Кроме этого код в основном остается таким же, как у вас.

Если вам на самом деле не нужны фиктивные значения, я бы полностью удалил этот самый внутренний цикл k.reserve зарезервирует пространство памяти, необходимое для реальных данных.

#include <vector>

using std::vector; // so we can just call it "vector"
typedef vector<vector<vector<double>>> doublecube;

static doublecube snapshot_transforms_function (int num_snapshots, int num_geometries)
{    
    // I deleted component_transform. It was never used

    doublecube snapshot_transforms;
    snapshot_transforms.reserve(num_snapshots);

    for (int i = 0; i < num_snapshots; i++)
    {
        snapshot_transforms.at(i).reserve(num_geometries);

        for (int j = 0; j < num_geometries; j++)
        {
            snapshot_transforms.at(i).at(j).reserve(16);

            // 4x4 transform put into a 1x16 array with dummy values for each component for each snapshot
            for (int k = 0; k < 16; k++)
                snapshot_transforms.at(i).at(j).at(k) = k;
        }
    }

    return snapshot_transforms;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...