Справка по 2D массиву в C ++ - PullRequest
1 голос
/ 23 марта 2011

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

class Vertex                                    // Vertex Class
{
public:
    float x;                                // X Component
    float y;                                // Y Component
    float z;                                // Z Component

    float getX() {
        return x;
    }
    float getY() {
        return y;
    }
    float getZ() {
        return z;
    }
};

Теперь мне нужно сделать из них двумерный массив, но когда я его инициализирую, он не будет работать.В основном каждый ряд будет гранью многоугольника.И каждый столбец будет содержать вершину этой строки.Поэтому, если одна строка равна

(0,0,0) (1, 1, 1) (3, 3, 3) (4,4,4);

, то эта строка будетпредставлять лицо с вершинами (0,0,0) (1, 1, 1) (3, 3, 3) (4,4,4);

Теперь, когда я пытаюсь инициализировать его, используя

Vertex faces = new Vertex[num_faces][4];

Работает, работает.Это кажется довольно простым, так что я делаю неправильно?

РЕДАКТИРОВАТЬ: я изменил его на

Vertex *faces = new Vertex[num_faces][4];

, и я получаю эту ошибку:

не может конвертировать из 'Vertex (*) [4] 'до' Vertex * '

Ответы [ 4 ]

3 голосов
/ 23 марта 2011
cannot convert from 'Vertex (*)[4]' to 'Vertex *'

Компилятор уже говорит вам, что вам нужно знать, просто измените тип faces:

Vertex (*faces)[4] = new Vertex[num_faces][4];
0 голосов
/ 24 марта 2011

«Двумерные массивы» являются злом ... они часто не совсем делают то, что вы надеетесь достичь.

Дело в том, что для компиляции кода необходимо либо перевернуть индексы, и в этом случае вы получите:

Vertex *faces[4] = {
    new Vertex[num_faces],
    new Vertex[num_faces],
    new Vertex[num_faces],
    new Vertex[num_faces]
};

Или вам придется использовать код, который разместил mkaes.

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

Для полностью «структурных» объектов, таких как этот, можно выполнить следующий трюк:

char *memblk =
    malloc(num_faces * 4 * sizeof(Vertex) + num_faces * sizeof(Vertex *));

Vertex **faces = static_cast<Vertex **>memblk;
Vertex *first = static_cast<Vertex *>(memblk + num_faces * sizeof(Vertex *));

for(i = 0; i < num_faces; first += 4, i++)
    faces[i] = first;

где вы выделяете один блок памяти, достаточно большой для хранения:

  1. массив Vertex * размера num_faces и
  2. num_faces массивы Vertex размера 4.

и затем инициализировать первый, чтобы он содержал соответствующие начальные адреса.

Чтобы «удалить» это, вам нужно будет снова использовать функцию C free(faces) - но это нормально для одного вызова.

Вышеупомянутое на самом деле довольно эффективно и близко соответствует виду низкоуровневого представления, например, Буферные объекты OpenGL Vertex используют для данных (на самом деле, их можно сделать так, чтобы они совпадали).

0 голосов
/ 23 марта 2011

Никогда не используйте массивы, когда векторы будут делать то же самое.Нужная вам структура данных: std::vector<std::vector<Vertex> >.

class Vertex {
    ...
    Vertex(float x, float y, float z) : x(x), y(y), z(z) {}
};

int main() {
    // a 1D array of vertices is a polygon
    std::vector<Vertex> square;
    square.push_back(Vertex(0, 0, 0));
    square.push_back(Vertex(0, 1, 0));
    square.push_back(Vertex(1, 1, 0));
    square.push_back(Vertex(1, 0, 0));

    // Another square, in a different plane
    std::vector<Vertex> square1;
    square1.push_back(Vertex(0, 0, 1));
    square1.push_back(Vertex(0, 1, 1));
    square1.push_back(Vertex(1, 1, 1));
    square1.push_back(Vertex(1, 0, 1));

    // A 2D array of vertices is a polyhedron.
    std::vector<std::vector<Vertex> > cube;
    cube.push_back(square);
    cube.push_back(square1);
    // need four more sides
}

Обратите внимание на полное отсутствие указателей, malloc или new.

Для повышения читабельности, я бы порекомендовал typedef std::vector<Vertex> polygon, typedef std::vector<polygon> polyhedron и либеральное использование функций из boost::assign.

0 голосов
/ 23 марта 2011

Вам нужно объявить двумерный массив для того, что вы хотите заархивировать.

Vertex **faces = new Vertex*[num_faces];
for(int i=0; i < num_faces; ++i)
    faces[i] = new Vertex[4];

Или, конечно, когда num_faces является постоянной времени компиляции, вы можете просто объявить массив следующим образом.

Vertex faces[num_faces][4];

Хороший ресурс динамических массивов с несколькими измерениями можно найти в c ++ - faq lite

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