我一直在试验 boost multi_array_refs,因为它们能够将世界的 2D(在我的例子中)阵列 View 映射到连续内存的任意 block 上。使用 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]);
}
最佳答案
初始化器列表中的初始化器按照类成员声明的顺序进行评估(基类之后的成员)。
因此,您可以通过将 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);
}
还请注意
- C++ 中没有 malloc 的位置
- 您应该防止类型被复制,否则您将对数据缓冲区进行两次
删除
。
其他想法
如果您的评论说:
//在实际应用中,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);
}
关于c++ - 实例化后更改 multi_array_ref 数据 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51732238/