C++ 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 创建一个二维数组。第一个维度中的元素数设置为 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 数组视为常量多维数组。
到此这篇关于C++ Boost MultiArray简化使用多维数组库的文章就介绍到这了,更多相关C++ Boost MultiArray内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!