Rio*_*iot 7 c++ boost pointers boost-multi-array multidimensional-array
我对使用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);
}
}
}
}
};
Run Code Online (Sandbox Code Playgroud)
之后,如果我尝试进行分配
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>'|
Run Code Online (Sandbox Code Playgroud)
"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)'|
Run Code Online (Sandbox Code Playgroud)
非常感谢任何建议,我相信我错过了一些明显的东西.
您的数组是值类型 ( octreenode),而不是指针类型 ( octreenode*)
因此,您不应该尝试将指针分配给动态分配的八叉树节点(new默认情况下用于堆分配)。
相反,只需分配一个值:
(*chunk)[cz][cx][cy] = octreenode(1,72);
Run Code Online (Sandbox Code Playgroud)
事实上,没有理由使用new事实上,一开始
在评论中,有人提出可以优化更多内容,并且您认为对有关编译错误的答案进行了有用的补充。
所以这里是:如果您确实想用完全相同的值初始化所有数组元素,
您可以通过暂时忘记数组形状来提高循环效率:
std::fill_n(chunk.data(), chunk.num_elements(), octreenode {1, 72});
Run Code Online (Sandbox Code Playgroud)
如果你知道octreenode是 POD 类型,你可以写
std::uninitialzed_fill_n(chunk.data(), chunk.num_elements(), octreenode {1, 72});
Run Code Online (Sandbox Code Playgroud)
但智能库的实现最终还是会调用fill_n(因为没有任何好处)。uninitialized_fill_n如果octreenode不是POD 类型,您可以使用它,但它很容易被破坏。
事实上,一开始也没有理由在 multi 数组上使用 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);
}
Run Code Online (Sandbox Code Playgroud)