简介
C++ 标准模板库 (STL) 作为 C++ 标准库的一部分,提供了一个用于在不同类型容器上处理算法的框架。然而,普通数组不提供 STL 容器的接口(尽管它们提供了 STL 容器的迭代器接口)。
作为普通数组的替代,STL 提供了类 std::vector
。然而,std::vector<>
提供了动态数组的语义。因此,它管理数据以便能够更改元素数量。如果只需要固定大小的数组,这会产生一些开销。
在他的书《Generic Programming and the STL》中,Matthew H. Austern 为固定大小的普通数组介绍了一个有用的包装类,称为 block
。它比普通数组更安全,性能也毫不逊色。在 Bjarne Stroustrup 的《The C++ Programming Language》第三版中,他介绍了一个类似的类,称为 c_array,我(Nicolai Josuttis)在我的书《The C++ Standard Library - A Tutorial and Reference》中对其进行了稍作修改,称之为 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);
效果 |
|
复杂度 |
线性复杂度 |
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 } };
请注意,如果初始化列表中的元素较少,那么剩余的每个元素都将获得默认初始化(因此,它具有一个定义值)。
然而,这种方法也有其缺点:**不传递初始化列表意味着元素具有未确定的初始值**,因为规则规定聚合可以具有
-
无用户声明的构造函数。
-
无私有或保护的非静态数据成员。
-
无基类。
-
无虚函数。
尽管如此,当前的实现采用了这种方法。
请注意,对于符合标准要求的编译器,可以使用更少的大括号(根据标准 8.5.1 (11))。也就是说,你可以像这样初始化一个数组:
boost::array<int,4> a = { 1, 2, 3 };
更多信息……
要查找有关在 C++ 中使用普通数组和 STL 框架的更多详细信息,请参阅例如:
The C++ Standard Library - A Tutorial and Reference
作者:Nicolai M. Josuttis
Addison Wesley Longman,1999 年
ISBN 0-201-37926-0