3

我想在一些代码中初始化一个 boost::multi_array 内联。但我不认为 boost::multi_array 支持从初始化列表进行初始化。这是我到目前为止所拥有的:

// First create a primitive array, which can be directly initialized
uint8_t field_primitive[4][8] = {
    { 1,1,1,1,1,1,1,1 },
    { 1,2,1,2,1,2,1,2 },
    { 1,1,2,2,2,2,2,2 },
    { 1,2,2,2,2,2,2,2 }
};
// Create the boost::multi_array I actually want to use
boost::multi_array<uint8_t, 2> field(boost::extents[4][8]);
// Compact but yucky approach to copying the primitive array contents into the multi_array.
memcpy(field.data(), field_primitive, field.num_elements() * sizeof(uint8_t));

我喜欢我可以使用花括号初始化器列表紧凑地表达矩阵内容。但我不喜欢“memcpy”,也不喜欢使用一次性原始数组。有没有更好的方法从代码中可读的内联值集填充我的 boost::multi_array ?

4

1 回答 1

1

以下来自官方 boost 文档中关于multi_array的示例也使用memcpy,尽管与origin(). 所以使用它似乎没问题:

#include <boost/multi_array.hpp>
#include <algorithm>
#include <iostream>
#include <cstring>

int main()
{
  boost::multi_array<char, 2> a{boost::extents[2][6]};

  typedef boost::multi_array<char, 2>::array_view<1>::type array_view;
  typedef boost::multi_array_types::index_range range;
  array_view view = a[boost::indices[0][range{0, 5}]];

  std::memcpy(view.origin(), "tsooB", 6);
  std::reverse(view.begin(), view.end());

  std::cout << view.origin() << '\n';

  boost::multi_array<char, 2>::reference subarray = a[1];
  std::memcpy(subarray.origin(), "C++", 4);

  std::cout << subarray.origin() << '\n';
} 

origin()关于和之间的区别data()多数组参考手册定义了以下内容:

元素*数据();这将返回一个指向包含数组数据的连续块的开头的指针。如果数组的所有维度都以 0 为索引并按升序存储,则相当于 origin()。

元素*原点();这将返回 multi_array 的原始元素。

data()因此,在使用andorigin()时,似乎有两件事要考虑memcpy, ff 数组包含非 0 索引或非升序的维度:

首先,origin()可能不指向数组使用的连续内存块的开始。因此,将多数组大小的内存复制到此位置可能会超出保留的内存块。

其次,另一方面,将内存块复制到data()的地址可能会导致内存布局,其中通过多数组访问的数组索引与复制到数组内部数据缓冲区中的内存块的索引不对应。

所以在我看来,使用memcpyto (pre)-fill a multiarray 应该小心使用,最好使用基于 0 的索引和升序。

于 2017-01-16T21:53:16.583 回答