std::array
是在C++ 11标准中增加的STL容器,它的设计目的是提供与原生数组类似的功能与性能。正因此,使得std::array
有很多与其他容器不同的特殊之处,比如:std::array
的元素是直接存放在实例内部,而不是在堆上分配间;std::array
的大小必须在编译期确定。std::array
的构造函数、析构函数和赋值操作符都是编译器隐式声明的……
std::array
底层是一段连续的固定大小的内存,实现是在struct
中定义数组作为成员变量:
std::array<int, 5> arr = {1, 2, 3, 4, 5};
arr
存储在栈中,对象中包含一个在栈上定义的数组
用于存储元素。容器的大小必须在编译期确定。std::array
定义如下。_M_elems
是定义的数组用于存储元素。 template<typename _Tp, std::size_t _Nm>
struct array
{
typedef _Tp value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* iterator; // 迭代器
typedef const value_type* const_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef std::reverse_iterator<iterator> reverse_iterator; // 反向迭代器
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
// Support for zero-sized arrays mandatory.
typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type; // *
typename _AT_Type::_Type _M_elems; // 定义的数组用于存储元素
...
__array_traits
的定义有两个版本,模板申明单参数(type
)和双参数(type
、size
),便实现size == 0
的array
的原理。 template<typename _Tp, std::size_t _Nm> // _Tp为元素类型、_Nm为容器大小size
struct __array_traits
{
typedef _Tp _Type[_Nm];
static constexpr _Tp&
_S_ref(const _Type& __t, std::size_t __n) noexcept
{ return const_cast<_Tp&>(__t[__n]); }
static constexpr _Tp*
_S_ptr(const _Type& __t) noexcept
{ return const_cast<_Tp*>(__t); }
};
template<typename _Tp> // _Tp为元素类型,容器大小默认为0
struct __array_traits<_Tp, 0>
{
struct _Type { };
static constexpr _Tp&
_S_ref(const _Type&, std::size_t) noexcept
{ return *static_cast<_Tp*>(nullptr); }
static constexpr _Tp*
_S_ptr(const _Type&) noexcept
{ return nullptr; }
};
at 通过下标获取对应元素引用
back 尾元素引用
begin iterator
cbegin const iterator
cend const iterator
crbegin iterator reverse iterator
crend iterator reverse reverse
data 底层数组
empty 容器是否为空
end iterator
fill 赋值
front 头元素引用
max_size
operator[] 通过下标获取元素引用
rbegin reverse iterator
rend reverse iterator
size
swap
std::array
作为聚合类,可以通过为类(default
、copy
、move
)隐式定义的函数来进行构造容器对象, 或使用 initializer lists 来构造对象:
int
,元素将保持未初始化状态;array
对象为static
的,则元素0
初始化。std::array<int, 10> static_arr; // 默认初始化,静态对象
int main() {
std::array<int, 10> arr;
for(auto& i:arr)
cout << i << " ";
cout << endl;
for(auto& i:static_arr) // 打印静态对象array中元素
cout << i << " ";
cout << endl;
return 0;
}
0 0 0 0 4197872 0 4197168 0 226809856 32765
0 0 0 0 0 0 0 0 0 0
arr
中元素为int 随机值。static_arr
内部元素进行了0初始化。
array
对象的元素 复制/移动 到构造的array
中。int main() {
std::array<int,3> arr = {1,2,3}; // initialized as: {1,2,3}
std::array<int,3> arr_copy = arr; // copy: {1,2,3}
return 0;
}
list
中的元素个数小于array.size
, 那么对于剩余元素将进行初始化(类类型为 默认初始化、 普通类型为0初始化)。int main() {
// initialized as: {1,2,3,0,0}
std::array<int,5> arr = {1,2,3};
return 0;
}
size()
,返回容器中元素个数。max_size()
,返回容器可以容乃的最大元素个数,返回值与size()
一样,总是等于第二个模板参数_Nm
。empty()
,返回容器是否为空,即容器size是否为0。constexpr size_type size() noexcept; // size 函数原型
constexpr size_type max_size() noexcept; // max_size
constexpr bool empty() noexcept; // empty
测试代码:
int main () {
std::array<int,5> arr_int;
std::cout << "size of arr_int: " << arr_int.size() << std::endl;
std::cout << "max_size of arr_int: " << arr_int.max_size() << '\n';
std::cout << "sizeof(arr_int): " << sizeof(arr_int) << std::endl;
std::cout << "arr_int " << (arr_int.empty() ? "is empty" : "is not empty") << '\n';
cout << endl;
std::array<int,0> arr_empty;
std::cout << "arr_empty " << (arr_empty.empty() ? "is empty" : "is not empty") << '\n';
std::cout << "sizeof(arr_empty): " << sizeof(arr_empty) << std::endl;
return 0;
}
size of arr_int: 5
max_size of arr_int: 5
sizeof(arr_int): 20
arr_int is not empty
aarr_empty is empty
sizeof(arr_empty): 1
arr_empty
使用array模板类创建的是一个空类,所有其实例化对象的sizeof
为1。fill()
,将容器中所有元素值设置为val
。data()
,返回指向容器中第一个元素的指针,后续可以通过指针偏移访问其他元素。swap()
,当前容器与,另一个相同类型、相同大小的array
交换容器中所有元素,如果类型或大小
不同,则无法通过编译。void fill(const value_type& val); // fill 函数原型
value_type* data() noexcept; // data
const value_type* data() const noexcept;
// swap
void swap (array& x) noexcept(noexcept(swap(declval<value_type&>(),declval<value_type&>())));
测试代码:
int main () {
std::array<int,3> arr_first;
arr_first.fill(9); // fill(), arr_first:9 9 9
std::array<int,3> arr_second = {10,100,1000};
arr_first.swap(arr_second); // 交换俩arr对象中元素
cout << "arr_first element: "; // data()函数获取头元素指针
int* p = arr_first.data(); // 通过指针偏移打印 arr_first 元素
for(int i=0; i<arr_first.size(); ++i)
cout << *(p+i) << " ";
return 0;
}
arr_first element: 10 100 1000