我一直在试验boost multi_array_refs,因为它们能够将世界的2D(以我为例)阵列视图映射到连续内存的任意块上。使用multi_array_ref时,将指向连续内存的指针指定给构造函数。效果很好,但是在我的最终应用程序中,我真正想做的是获取一个预先存在的multi_array_ref对象,并将其指向动态分配的新缓冲区。似乎应该可行,但是我似乎不知道该怎么做。我希望这里有一些基本代码可以演示我要尝试做的事情的类型,尽管它显然不能按编写的方式工作。
const int XSIZE = 10;
const int YSIZE = 5;
typedef boost::multi_array_ref<int, 2> ARRAY_2D_REF;
class Test2D {
public:
Test2D(const int sizeX, const int sizeY);
~Test2D();
// I want to point this multi_array_ref to a buffer that gets
// allocated in the constructor.
ARRAY_2D_REF data;
private:
int xSize;
int ySize;
int *n;
};
// can't construct 'data' using ':' syntax here, because, the 'n'
// buffer has not been allocated yet so 'n' doesn't contain a valid
// address. This compiles okay, but segfaults if you try to use 'data'
// because 'n' contains garabge at this point.
Test2D::Test2D(const int sizeX, const int sizeY) : data(n, boost::extents[sizeX][sizeY]) // <<-- fail
{
xSize = sizeX;
ySize = sizeY;
// In the actual application, n will be populated by data arriving
// on TCP stream. The header on those mesasges contain total
// contiguous buffer size and X,Y dimensions, followed by the data.
n = (int*)malloc(xSize * ySize * sizeof(int));
// I want to set the multi_array_ref origin and define extents right
// here. The thought was to set the origin to 'n', and then
// resize(), but how? Of course I can't actually construct it here
// as shown. Seems like there should be a simple way to set
// (change) the origin pointer. There probably is in fact. But I
// can't seem to figure it out.
data(n, boost::extents[xSize][ySize]);
}
答案 0 :(得分:0)
初始化器列表中的初始化器按照类成员(基类之后的成员)的声明顺序进行求值。
因此,您可以通过将data
成员声明移到其他成员之后来解决所有问题。
#include <boost/multi_array.hpp>
static const int XSIZE = 10;
static const int YSIZE = 5;
typedef boost::multi_array_ref<int, 2> ARRAY_2D_REF;
class Test2D {
public:
Test2D(const int sizeX, const int sizeY)
: xSize(sizeX),
ySize(sizeY),
n (new int[xSize*ySize]),
data(n, boost::extents[xSize][ySize])
{ }
~Test2D() {
delete n;
}
Test2D(Test2D const&) = delete; // Rule Of Three!
private:
int xSize;
int ySize;
int *n;
public:
ARRAY_2D_REF data;
};
int main() {
Test2D wrapped(XSIZE, YSIZE);
}
注意也
delete
}。如果您的评论说,从构造函数内部分配缓冲区(无论是body还是initializer-list),实际上没有任何意义。
//在实际的应用程序中,n将由到达的数据填充 //在TCP流上。这些消息的标题包含总计 //连续的缓冲区大小和X,Y维度,后跟数据。
构造函数没有进行分配所必需的依赖关系,也不应该进行分配。有两种选择:
如果缓冲区始终由Test2D
实例拥有(并且将从IO缓冲区复制数据),则只需使用multi_array
,不是multi_array_ref
。它会安全地为您分配资源。
否则,传入缓冲区:
#include <boost/multi_array.hpp>
#include <memory>
static const int XSIZE = 10;
static const int YSIZE = 5;
static const int HEADER_SIZE = 16;
typedef boost::const_multi_array_ref<int, 2> ArrayCRef;
class Test2D {
public:
Test2D(int const* raw, int sizeX, int sizeY) : data(raw, boost::extents[sizeX][sizeY])
{ }
ArrayCRef::size_type xSize() const { return data.shape()[0]; }
ArrayCRef::size_type ySize() const { return data.shape()[1]; }
public:
ArrayCRef data;
};
int main() {
auto io_buf = std::make_unique<char[]>(XSIZE*YSIZE*sizeof(int)+HEADER_SIZE);
// TODO parse XSIZE/YSIZE from io_buf
auto raw = reinterpret_cast<int const*>(io_buf.get() + HEADER_SIZE);
Test2D wrapped(raw, XSIZE, YSIZE);
}