简介
C++ 标准模板库 STL 作为 C++ 标准库的一部分,为处理不同类型容器的算法提供了一个框架。然而,普通数组不提供 STL 容器的接口(尽管它们提供了 STL 容器的迭代器接口)。
作为普通数组的替代品,STL 提供了类 std::vector
。然而,std::vector<>
提供了动态数组的语义。因此,它管理数据以便能够更改元素数量。这在只需要静态大小的数组时会导致一些开销。
Matthew H. Austern 在他的著作《泛型编程与 STL》中,介绍了一个用于静态大小的普通数组的有用包装类,名为 block
。它比普通数组更安全,并且性能不差。Bjarne Stroustrup 在《C++ 编程语言》第三版中,介绍了一个类似的类,名为 c_array,我 (Nicolai Josuttis) 在我的著作《C++ 标准库——教程与参考》中对其进行了略微修改,名为 carray
。这是这些方法的精髓,并融入了来自 Boost 的许多反馈。
在考虑了不同的名称之后,我们决定将此类简单地命名为 array
。
请注意,建议此类作为下一个技术报告的一部分,这将扩展 C++ 标准(参见 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1548.htm)。
更新:std::array
(从 C++11 开始)是 C++ 标准的一部分。boost::array
和 std::array
之间的差异很小。如果您正在使用 C++11,则应考虑使用 std::array
而不是 boost::array
。
类 array
满足“可逆容器”的大部分但并非全部要求(参见 C++ 标准第 23.1 节,[lib.container.requirements])。array
不是可逆 STL 容器的原因是因为
-
没有提供构造函数。
-
元素可能具有不确定的初始值(请参阅名为“设计原理”的章节)。
-
swap()
没有恒定复杂度。 -
size()
始终是常量,基于类型的第二个模板参数。 -
容器不提供分配器支持。
它不满足“序列”的要求(参见 C++ 标准第 23.1.1 节,[lib.sequence.reqmts]),除非
-
提供了
front()
和back()
。 -
提供了
operator[]
和at()
。
修订历史
1.88.0 版本中的更改
-
将文档转换为 AsciiDoc (Christian Mazakas)。
-
根据需要添加了
noexcept
和constexpr
。 -
将过时的函数标记为已弃用。
-
删除了过时的编译器解决方法。
-
更改了
array<T, 0>::begin()
、cbegin()
、end()
、cend()
以返回nullptr
,从而启用constexpr
。这与std::array
的行为相匹配。 -
删除了本地
hash_value
重载;boost::hash
本机支持类似数组的类型。 -
现在可以使用
= {{}}
初始化array<T, 0>
。 -
添加了
operator<=>
。 -
添加了
to_array
。
参考
头文件 <boost/array.hpp>
namespace boost {
template<typename T, std::size_t N> class array;
template<typename T, std::size_t N>
void swap(array<T, N>&, array<T, N>&);
template<typename T, std::size_t N>
constexpr bool operator==(const array<T, N>&, const array<T, N>&);
template<typename T, std::size_t N>
constexpr bool operator!=(const array<T, N>&, const array<T, N>&);
template<typename T, std::size_t N>
constexpr bool operator<(const array<T, N>&, const array<T, N>&);
template<typename T, std::size_t N>
constexpr bool operator>(const array<T, N>&, const array<T, N>&);
template<typename T, std::size_t N>
constexpr bool operator<=(const array<T, N>&, const array<T, N>&);
template<typename T, std::size_t N>
constexpr bool operator>=(const array<T, N>&, const array<T, N>&);
template<typename T, std::size_t N>
constexpr auto operator<=>(const array<T, N>&, const array<T, N>&);
template<std::size_t Idx, typename T, std::size_t N>
constexpr T& get(array<T, N>&) noexcept;
template<std::size_t Idx, typename T, std::size_t N>
constexpr const T& get(const array<T, N>&) noexcept;
template<class T, std::size_t N>
constexpr array<T, N> to_array( T const (&)[N] );
template<class T, std::size_t N>
constexpr array<T, N> to_array( T (&&)[N] );
template<class T, std::size_t N>
constexpr array<T, N> to_array( T const (&&)[N] );
}
类模板 array
概要
// In header: <boost/array.hpp>
template<typename T, std::size_t N>
class array {
public:
// types
typedef T value_type;
typedef T* iterator;
typedef const T* const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef T& reference;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
// static constants
static const size_type static_size = N;
// construct/copy/destroy
template<typename U> array& operator=(const array<U, N>&);
// iterator support
constexpr iterator begin() noexcept;
constexpr const_iterator begin() const noexcept;
constexpr const_iterator cbegin() const noexcept;
constexpr iterator end() noexcept;
constexpr const_iterator end() const noexcept;
constexpr const_iterator cend() const noexcept;
// reverse iterator support
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator crbegin() const noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
const_reverse_iterator crend() const noexcept;
// capacity
static constexpr size_type size() noexcept;
static constexpr bool empty() noexcept;
static constexpr size_type max_size() noexcept;
// element access
constexpr reference operator[](size_type);
constexpr const_reference operator[](size_type) const;
constexpr reference at(size_type);
constexpr const_reference at(size_type) const;
constexpr reference front();
constexpr const_reference front() const;
constexpr reference back();
constexpr const_reference back() const;
constexpr T* data() noexcept;
constexpr const T* data() const noexcept;
T* c_array() noexcept; // deprecated
// modifiers
swap(array<T, N>&);
constexpr void fill(const T&);
void assign(const T&); // deprecated
// public data members
T elems[N];
};
构造/复制/销毁
template<typename U> array& operator=(const array<U, N>& other);
效果 |
对于 |
迭代器支持
constexpr iterator begin() noexcept;
constexpr const_iterator begin() const noexcept;
constexpr const_iterator cbegin() const noexcept;
返回 |
|
constexpr iterator end() noexcept;
constexpr const_iterator end() const noexcept;
constexpr const_iterator cend() const noexcept;
返回 |
|
反向迭代器支持
reverse_iterator rbegin() noexcept;
返回 |
|
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator crbegin() const noexcept;
返回 |
|
reverse_iterator rend() noexcept;
返回 |
|
const_reverse_iterator rend() const noexcept;
const_reverse_iterator crend() const noexcept;
返回 |
|
容量
static constexpr size_type size() noexcept;
返回 |
|
static constexpr bool empty() noexcept;
返回 |
|
static constexpr size_type max_size() noexcept;
返回 |
|
元素访问
constexpr reference operator[](size_type i);
constexpr const_reference operator[](size_type i) const;
要求 |
|
返回 |
|
抛出 |
无。 |
constexpr reference at(size_type i);
constexpr const_reference at(size_type i) const;
返回 |
|
抛出 |
如果 |
constexpr reference front();
constexpr const_reference front() const;
要求 |
|
返回 |
|
抛出 |
无。 |
constexpr reference back();
constexpr const_reference back() const;
要求 |
|
返回 |
|
抛出 |
无。 |
constexpr T* data() noexcept;
constexpr const T* data() const noexcept;
返回 |
|
T* c_array() noexcept; // deprecated
返回 |
|
备注 |
此函数已弃用。请改用 |
修改器
void swap(array<T, N>& other);
效果 |
|
复杂度 |
线性于 N。 |
void fill(const T& value);
效果 |
对于 |
void assign(const T& value); // deprecated
效果 |
|
备注 |
|
比较
template<typename T, std::size_t N>
constexpr bool operator==(const array<T, N>& x, const array<T, N>& y);
返回 |
|
template<typename T, std::size_t N>
constexpr bool operator!=(const array<T, N>& x, const array<T, N>& y);
返回 |
|
template<typename T, std::size_t N>
constexpr bool operator<(const array<T, N>& x, const array<T, N>& y);
返回 |
|
template<typename T, std::size_t N>
constexpr bool operator>(const array<T, N>& x, const array<T, N>& y);
返回 |
|
template<typename T, std::size_t N>
constexpr bool operator<=(const array<T, N>& x, const array<T, N>& y);
返回 |
|
template<typename T, std::size_t N>
constexpr bool operator>=(const array<T, N>& x, const array<T, N>& y);
返回 |
|
template<typename T, std::size_t N>
constexpr auto operator<=>(const array<T, N>& x, const array<T, N>& y)
-> decltype(x[0] <=> y[0]);
效果 |
对于 |
备注 |
当 |
特化
template<std::size_t Idx, typename T, std::size_t N>
constexpr T& get(array<T, N>& arr) noexcept;
强制要求 |
|
返回 |
|
template<std::size_t Idx, typename T, std::size_t N>
constexpr const T& get(const array<T, N>& arr) noexcept;
强制要求 |
|
返回 |
|
创建
template<class T, std::size_t N>
constexpr array<T, N> to_array( T const (&a)[N] );
返回 |
一个 |
template<class T, std::size_t N>
constexpr array<T, N> to_array( T (&&a)[N] );
返回 |
一个 |
template<class T, std::size_t N>
constexpr array<T, N> to_array( T const (&&a)[N] );
返回 |
一个 |
设计原理
关于构造函数,存在一个重要的设计权衡:我们可以将 array 实现为“聚合”(参见 C++ 标准第 8.5.1 节,[dcl.init.aggr])。这意味着
-
数组可以使用花括号括起来的、逗号分隔的初始化列表进行初始化,该列表用于容器元素的初始化,并按递增的下标顺序书写
boost::array<int,4> a = { { 1, 2, 3 } };
请注意,如果初始化列表中的元素较少,则每个剩余元素都将进行默认初始化(因此,它具有确定的值)。
然而,这种方法有其缺点:不传递初始化列表意味着元素具有不确定的初始值,因为规则规定聚合可能具有
-
没有用户声明的构造函数。
-
没有私有或受保护的非静态数据成员。
-
没有基类。
-
没有虚函数。
然而,当前的实现使用了这种方法。
请注意,对于符合标准的编译器,可以使用更少的大括号(根据 C++ 标准的 8.5.1 (11))。也就是说,您可以按如下方式初始化数组
boost::array<int,4> a = { 1, 2, 3 };
更多信息…
要查找有关在 C++ 中使用普通数组和 STL 框架的更多详细信息,请参阅例如
C++ 标准库——教程与参考
Nicolai M. Josuttis 著
Addison Wesley Longman,1999
ISBN 0-201-37926-0