亲宝软件园·资讯

展开

C++ Boost MultiArray简化使用多维数组库

无水先生 人气:0

一、介绍Boost.MultiArray

Boost.MultiArray

Boost.MultiArray 是一个简化使用多维数组的库。最重要的优点是多维数组可以像标准库中的容器一样使用。例如,有一些成员函数,例如 begin() 和 end(),让您可以通过迭代器访问多维数组中的元素。迭代器比通常用于 C 数组的指针更易于使用,尤其是对于具有多个维度的数组。

二、示例

示例 19.1。带有 boost::multi_array 的一维数组

#include <boost/multi_array.hpp>
#include <iostream>
int main()
{
  boost::multi_array<char, 1> a{boost::extents[6]};
  a[0] = 'B';
  a[1] = 'o';
  a[2] = 'o';
  a[3] = 's';
  a[4] = 't';
  a[5] = '\0';
  std::cout << a.origin() << '\n';
}

Boost.MultiArray 提供类 boost::multi_array 来创建数组。这是提供的最重要的类。它在 boost/multi_array.hpp 中定义。

boost::multi_array 是一个需要两个参数的模板:第一个参数是要存储在数组中的元素的类型。第二个参数确定数组应该有多少维。

第二个参数只设置维度的数量,而不是每个维度中的元素数量。因此,在示例 19.1 中,a 是一维数组。

维度中的元素数量是在运行时设置的。示例 19.1 使用全局对象 boost::extents 来设置维度大小。该对象被传递给 a 的构造函数。

boost::multi_array 类型的对象可以像普通的 C 数组一样使用。通过将索引传递给 operator[] 来访问元素。示例 19.1 将五个字母和一个空字符存储在 a - 一个包含六个元素的一维数组中。 origin() 返回指向第一个元素的指针。该示例使用此指针将存储在数组中的单词 -Boost - 写入标准输出。

与标准库中的容器不同,operator[] 检查索引是否有效。如果索引无效,程序将使用 std::abort() 退出。如果您不想检查索引的有效性,请在包含 boost/multi_array.hpp 之前定义宏 BOOST_DISABLE_ASSERTS。

示例 19.2。二维数组的视图和子数组

#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';
}

Example19.2

example19.2 创建一个二维数组。第一个维度中的元素数设置为 2,第二个维度中的元素数设置为 6。将数组视为具有两行六列的表。

表的第一行将包含单词 Boost。由于这个词只需要存储五个字母,因此创建了一个视图,该视图正好跨越数组的五个元素。

基于类 boost::multi_array::array_view 的视图允许您访问数组的一部分并将该部分视为单独的数组。

boost::multi_array::array_view 是一个模板,它将视图中的维数作为模板参数。在示例 19.2 中,视图的维数为 1。由于数组 a 有两个维度,因此忽略了一个维度。为了省去Boost这个词,一维数组就足够了;更多的维度会令人困惑。

与 boost::multi_array 一样,维数作为模板参数传入,每个维的大小在运行时设置。但是,对于 boost::multi_array::array_view,这不是通过 boost::extents 完成的。相反,它是通过 boost::indices 完成的,这是 Boost.MultiArray 提供的另一个全局对象。

与 boost::extents 一样,索引必须传递给 boost::indices。虽然只能将数字传递给 boost::extents,但 boost::indices 也接受范围。这些是使用 boost::multi_array_types::index_range 定义的。

在示例 19.2 中,传递给 boost::indices 的第一个参数不是范围,而是数字 0。传递数字时,您不能使用 boost::multi_array_types::index_range。在示例中,视图将采用 a 的第一个维度——索引为 0 的维度。

对于第二个参数,boost::multi_array_types::index_range 用于定义范围。通过将 0 和 5 传递给构造函数,a 的第一个维度的前五个元素可用。范围从索引 0 开始,到索引 5 结束——不包括索引 5 处的元素。第一维中的第六个元素被忽略。

因此,视图是一个由五个元素组成的一维数组——a 的第一行中的前五个元素。当访问视图以使用 std::memcpy() 复制字符串并使用 std::reverse() 反转元素时,这种关系无关紧要。创建视图后,它就像一个具有五个元素的独立数组。

当对 boost::multi_array 类型的数组调用 operator[] 时,返回值取决于

方面。在示例 19.1 中,运算符返回 char 元素,因为访问的数组是一维的。

在示例 19.2 中,a 是一个二维数组。因此,operator[] 返回子数组而不是 char 元素。因为子数组的类型不是公开的,所以必须使用 boost::multi_array::reference。此类型与 boost::multi_array::array_view 不同,即使子数组的行为类似于视图。视图必须明确定义并且可以跨越数组的任意部分,而子数组由 operator[] 自动返回并跨越每个维度中的所有元素。

示例 19.3。使用 boost::multi_array_ref 包装 C 数组

#include <boost/multi_array.hpp>
#include <algorithm>
#include <iostream>
#include <cstring>
int main()
{
  char c[12] =
  {
    't', 's', 'o', 'o', 'B', '\0',
    'C', '+', '+', '\0', '\0', '\0'
  };
  boost::multi_array_ref<char, 2> a{c, 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::reverse(view.begin(), view.end());
  std::cout << view.origin() << '\n';
  boost::multi_array<char, 2>::reference subarray = a[1];
  std::cout << subarray.origin() << '\n';
}

类 boost::multi_array_ref 包装了一个现有的 C 数组。在示例 19.3 中,a 提供与 boost::multi_array 相同的接口,但不分配内存。使用 boost::multi_array_ref,一个 C 数组——不管它有多少维——都可以被视为一个 boost::multi_array 类型的多维数组。 C 数组只需要作为附加参数添加到构造函数中。

Boost.MultiArray 还提供了 boost::const_multi_array_ref 类,它将 C 数组视为常量多维数组。

加载全部内容

相关教程
猜你喜欢
用户评论