c++ - 实例化后更改 multi_array_ref 数据 block

标签 c++ multidimensional-array boost

我一直在试验 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/

相关文章:

c++ - 获取有关 boost::any 中包含的类型的信息

c++ - VC++ 自动说明符假定 vector<bool>::back 的引用限定符

c++ - 访问 2D valarrays 的列切片

c++ - Boost.Thread 类 CEvent 行为

c++ - 包含 boost::optional 对象的 std::vector 对象是否可移动?可移动 boost::可选?

c++ - 我应该从 Boost::filesystem::copy 得到什么错误代码

c++ - 为什么 M::operator<< 导致链接错误而不是 std::cout::operator<<

php - 从 MySQL 查询中获取行数组?

c - 如何使用单个指针定义二维数组

c++ - 调用 get 后将 shared_ptr 分配给另一个