从初始化列表中填充boost :: multi_array的最佳方法是什么?

时间:2017-01-16 21:14:45

标签: c++ c++11 boost boost-multi-array

我想在某些代码中初始化一个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?

1 个答案:

答案 0 :(得分:1)

有关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()之间的区别,multiarray reference manual定义了以下内容:

  

element * data();这会返回一个指向开头的指针   包含数组数据的连续块。如果所有的尺寸   数组是0索引并按升序存储,这是   相当于origin()。

     

element * origin();这将返回multi_array的origin元素。

因此,将data()origin()memcpy一起使用时,似乎需要考虑两件事,如果数组包含未按0索引或不按升序排列的维度:

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

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

所以在我看来,使用memcpy来预先填充多个阵列应该小心使用,理想情况下使用基于0的索引和升序。