указатели на класс в динамически распределенном boost multi_array, не компилируемый

Я довольно новичок в C ++ с Boost.

Я хочу, чтобы объект класса «world» имел массив с именем «chunk» типа «octreenode». Раньше у меня был обычный одномерный массив, и это работало нормально. Сейчас я пытаюсь перейти на использование трехмерного массива с функциональностью Boost multi_array, и я действительно не уверен, что делаю неправильно.

Упрощенный код:

class world {
public:

typedef boost::multi_array<octreenode, 3> planetchunkarray;  // a boost_multi for chunks
typedef planetchunkarray::index index;
planetchunkarray *chunk;

world(double x,double y,double z,
int widtheast, int widthnorth, int height) :
originx(x), originy(y), originz(z),
chunkseast(widtheast), chunksnorth(widthnorth), chunksup(height) {

chunk = new planetchunkarray(boost::extents[chunksnorth][chunkseast][chunksup]);
planetchunkarray::extent_gen extents;

for (int cz = 0; cz < chunksnorth; ++cz) {
for (int cx = 0; cx < chunkseast; ++cx) {
for (int cy = 0; cy < chunksup; ++cy) {
(*chunk)[cz][cx][cy] = new octreenode(1,72);
}
}
}
}
};

После чего, если я попытаюсь сделать назначение

root-> planet [0] -> chunk [0] [0] [0] -> material = 4;

Я получаю ошибку:

error: base operand of '->' has non-pointer type 'boost::detail::multi_array::sub_array<octreenode, 1u>'|

«octreenode» имеет соответствующий конструктор, и эта строка работала в идентичном синтаксисе, когда она была просто:

root-> planet [0] -> chunk [0] -> material = 4;

(с одномерным массивом). Точно так же, хотя он прекрасно компилируется с одномерным массивом, пытаясь передать чанк функциям, которые ожидают указатель на объект «octreenode», например:

compactoctree (root-> planet [p] -> chunk [cz] [cx] [cy], 0, 14);

генерирует ошибку

error: cannot convert 'boost::detail::multi_array::sub_array<octreenode, 1u>' to 'octreenode*' for argument '1' to 'short int compactoctree(octreenode*, int, int)'|

Буду очень признателен за любые предложения, я уверен, что упускаю что-то очевидное.

7

Решение

Ваш массив имеет тип значения (octreenode), а не тип указателя (octreenode*)

Следовательно, вы не должны пытаться назначить указатель на динамически размещаемый octreenode (new по умолчанию для выделения кучи).

Вместо этого просто присвойте значение:

      (*chunk)[cz][cx][cy] = octreenode(1,72);

На самом деле, нет причин использовать new на мульти-массиве в первую очередь:

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

Так что здесь: если вы действительно хотите инициализировать все элементы массива с одинаковым значением,

  1. Вы можете сделать циклы более эффективными, на мгновение забыв о формах массива:

    std::fill_n(chunk.data(), chunk.num_elements(), octreenode {1, 72});
    

    Если вы знаете octreenode это тип POD, вы мог записывать

    std::uninitialzed_fill_n(chunk.data(), chunk.num_elements(), octreenode {1, 72});
    

    но реализация умной библиотеки в конечном итоге вызовет fill_n в любом случае (потому что нет выгоды). Ты можешь использовать uninitialized_fill_n если octreenode является не тип POD, но это является тривиально разрушаемо.

  2. На самом деле, нет никакой причины использовать new в мульти-массиве. Вы можете просто использовать список инициализации конструктора для создания члена multi_array


Жить на Колиру

#include <boost/multi_array.hpp>
#include <type_traits>

struct octreenode { int a; int b; };

class world {
public:
world(double x, double y, double z, int widtheast, int widthnorth, int height)
:
originx(x), originy(y), originz(z),
chunkseast(widtheast), chunksnorth(widthnorth), chunksup(height),
chunk(boost::extents[chunksnorth][chunkseast][chunksup])
{
octreenode v = { 1, 72 };
std::fill_n(chunk.data(), chunk.num_elements(), v);
}

private:
double originx, originy, originz;
int chunkseast, chunksnorth, chunksup;

typedef boost::multi_array<octreenode, 3> planetchunkarray; // a boost_multi for chunks
typedef planetchunkarray::index index;
planetchunkarray chunk;
};

int main() {
world w(1,2,3,4,5,6);
}
4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]