Какой может быть лучший подход для хранения 2D массива объектов?

0

Я хочу сохранить объекты C++ в таблице MxN, и я хочу создать объект как:

Vector2D<MyObject*> objects = new Vector2D<MyObject*>(M,N);
MyObject* obj = new MyObject;
objects.add(i,j, obj);

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

EDIT: В основном, что мне нужно, просто выделите память для сетки MxN общего объекта. Просто добавьте/извлеките элементы с указанной строкой и столбцом.

  • 1
    MyObject obj = new MyObject; не компилируется.
  • 0
    Вы хотите создать их в стеке или в куче?
Показать ещё 3 комментария
Теги:
multidimensional-array

6 ответов

2

Кажется, вы пришли из мира Java или С# в области C++. Добро пожаловать. В C++ у вас есть автоматический объект хранения, и вам не нужно ничего new. Этого достаточно, если у вас также есть класс Vector2D.

Vector2D<MyObject> objects(M,N);
MyObject obj;
objects.add(i,j, obj);

В противном случае вы можете сделать 2D-вектор по std::vector:

std::vector<std::vector<MyObject>> objects;
  • 0
    Да, я из происхождения Java. Теперь проблема в том, что мне нужен класс Vector2D. Я спрашиваю, что может быть лучше для его реализации.
  • 0
    @ dg_no_9: я написал образец по std::vector .
Показать ещё 5 комментариев
1

Вы можете сделать 2D-вектор. Ссылка: std::vector:

std::vector<std::vector<MyObject>> objects;

Но перед использованием этого объекта вы должны были сделать этот объект.

// you know the size of your 2D : MaxRow, MaxCol
std::vector<std::vector<MyObject> > objects(MaxRow, 
                               std::vector<MyObject>(MaxCol, MyObject());

Или вы можете

std::vector<std::vector<MyObject> > objects;
for(size_t r_i=0; r_i<MaxRow; ++r_i) {
      // create and push a row in the 2D matrix.
      objects.push_back(std::vector<MyObject>());
      for(size_t c_i=0; c_i<MaxCol; ++c_i) {
           // push a col in the new created row.
           objects[r_i].push_back(MyObject());
      }
 }

Теперь вы хотите получить доступ к своей матрице.

size_t row, col;
// now you know your row and col : input or from anywhere

Допустим, что у вас есть функция callObject функции в классе MyObject.

// you can do this.
objects[row][col].callObject();

Но если вы хотите хранить разреженные матрицы, вы можете сделать

std::vector<std::vector<MyObject*>objects(MaxRow, 
                           std::vector<MyObject>(MaxCol, nullptr);
objects[2][3] = new MyObject(/*your arguments*/);

objects[2][3].callObject();

objects[0][0].callObject(); // Boom !!! Null pointer here.

С помощью указателей используйте std :: unique_ptr или std :: shared_ptr.


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

 typedef MyObject T;
 class Vector2D {
      std::vector<std::vector<T> > objects;
      public:
      // initialize the objects with MaxRow rows each with MaxCol cols.
      Vector2D(size_t MaxRow, size_t MaxCol);
      // remember that there should already be somebody at this row or col
      // or you have to create all the rows before this row and all the cols before
      // this col in this row.
      void addItem(size_t row, size_t col, const MyObject & obj);   
 };

Я использовал typedef int T потому что было бы легче менять шаблоны.


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

 typedef MyObject T;
 class Vector2D {
      std::vector<std::vector<std::unique_ptr<T> > > objects;
      public:
      // initialize the Nullptr with MaxRow rows each with MaxCol cols.
      Vector2D(size_t MaxRow, size_t MaxCol);
      // now you can just add the item, as pointer is already there.
      void addItem(size_t row, size_t col, MyObject * obj);   
 };

Использование unique_ptr по мере удаления и других ссылок.


Вы могли бы "получить много других вещей", наследуя std::vector< std::vector<T> > в Vector2D, но состав в большинстве случаев лучше, чем наследование.

  • 0
    Спасибо, похоже хороший способ. Я просто попробую это. :)
  • 0
    Что может быть лучшим способом реализовать функциональность addItem (row, col, MyObject) на вашем пути?
Показать ещё 1 комментарий
1

Самый простой способ:

vector<vector<MyObject>> objects ;

К сожалению, вам придется написать код для инициализации каждой строки до размера N.

Существует хорошая лекция на сайте microsoft channel9, где Стефан Т. Лававей (да, его инициалы STL) делает именно это для решения головоломки nurikabe.

C9 - Лекция STL - Решитель Nurikabe

0

С помощью современного компилятора С++ 11 вы можете использовать встроенный array и initializer_lists и он будет выглядеть примерно так:

    #include <array>
    using namespace std;
    ...

    vector<vector<int>> Objects;

    // Initialization
    Objects = {{1,2,3}, {4,4,5}};
    // Iterating
    for ( auto it = Objects.begin(); it != Objects.end(); ++it) {
      // you can access the arrays with *it in here
      for( auto it2 = *it->begin(); it2 != *it->end(); ++it2) {
        // you can access values directly with *it2
        *it2 = 1;
      }
    }

Вы можете использовать auto и позволить компилятору определить тип, как я, или вы можете указать, что it и it2 фактически являются векторными итераторами.

0

лучше использовать массив STRUCT, поле STRUCT зависит от того, какое поле MyObject

0

Я бы создал вектор векторов и перегрузил все необходимые операторы. Таким образом, вы можете повторно использовать реализацию std. Но прежде всего подумайте, как вы хотите получить доступ к этому Vector2D. Действительно ли это вектор или другой тип хранилища.

  • 0
    Я просто хочу получить доступ к 2d массиву с индексом строки, столбца. Например, для array.getObj (row, col);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню