7

我对使用 Boost 的 C++ 很陌生。

我想要一个“world”类的对象有一个名为“chunk”的“octreenode”类型的数组。以前我有一个普通的一维数组,这很好用。现在我正在尝试使用具有 Boost 的 multi_array 功能的 3D 数组,但我真的不确定自己做错了什么。

简化代码:

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);
        }
      }
    }
  }
};

之后,如果我尝试分配

根->行星[0]->块[0][0][0]->材料= 4;

我得到错误:

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

“octreenode”具有相关的构造函数,并且这一行的语法与之前相同:

根->行星[0]->块[0]->材料=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)'|

非常感谢您的任何建议,我确定我遗漏了一些明显的东西。

4

1 回答 1

4

您的数组是值类型 ( 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_nifoctreenode不是POD 类型,但它很容易破坏。

  2. 事实上,一开始也没有理由在 multi 数组上使用 new 。您可以只使用构造函数初始化列表来构造 multi_array 成员


Live On Coliru

#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);
}
于 2015-01-09T20:14:48.790 回答