STL:std::array 和 基本数组类型array 浅谈一二三

2023-12-26 15:12

本文主要是介绍STL:std::array 和 基本数组类型array 浅谈一二三,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、优缺点比较

在C++中,std::array是标准库提供的数组容器,相比于基础数据类型的数组,它具有以下优点和缺点:

优点:

    1. 安全性:std::array提供了边界检查,可以避免数组越界访问的问题。
    1. 可以作为函数参数:std::array可以作为函数的参数和返回值,而基础数据类型的数组不能直接作为函数参数传递。
    1. 支持STL算法:std::array可以直接使用STL算法,如std::sortstd::find等,而基础数据类型的数组需要手动实现这些算法。

缺点:

    1. 大小固定:std::array的大小在编译时就需要确定,无法动态改变大小,而基础数据类型的数组可以使用newdelete动态分配和释放内存。
    1. 初始化复杂:相比于基础数据类型的数组,std::array的初始化语法可能更加繁琐。std::array 不支持参数列表的初始化形式。

总的来说,std::array相比于基础数据类型的数组更加安全和方便,但在某些情况下可能会有一些额外的开销和限制。

二、代码示例

#include <any>
#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <array>
#include <set>
#include <queue>
#include <deque>
#include <algorithm>
using namespace std;#define NOUSE(x) (void)x;// test array
template <typename _Ty,size_t N>
void array_test_func(std::array<_Ty,N>& arr)
{/// 通过迭代器遍历auto traver_1 = [&](){
#if 0auto iter = arr.begin();for(;iter != arr.end();++iter)cout << *iter << " ";
#elsestd::copy(arr.cbegin(), arr.cend(), std::ostream_iterator<_Ty>(std::cout, " "));
#endifcout << endl;};traver_1();cout << "back  ==> " << arr.back() << endl;     // 首字符cout << "front ==> " << arr.front() << endl;    // 尾字符size_t n =  arr.size(); // 长度/// 通过数组指针遍历auto traver_2 = [&](){_Ty* dptr = arr.data(); // 首地址for(size_t i = 0; i < n ;++i){cout << *(dptr+i) << " ";}cout << endl;};traver_2();/// 通过下标遍历auto traver_3 = [&](){for(size_t i = 0; i < n;++i){cout << arr.at(i) << " ";}cout << endl;};traver_3();
}int main(int argc, char *argv[])
{NOUSE(argc);NOUSE(argv);std::array<int,3> arr = {2,6,4};array_test_func<int,3>(arr);// array_test_func<int,3>({2,4,6}); // error : 不支持 initializer_liststd::sort(arr.begin(),arr.end()); // 支持STL算法array_test_func<int,3>(arr);return 0;
}

三、源码赏析

// array standard header// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception#pragma once
#ifndef _ARRAY_
#define _ARRAY_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#include <xutility>#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new_STD_BEGIN
#if _ITERATOR_DEBUG_LEVEL != 0
struct _Iterator_base12_compatible { // TRANSITION, for binary compatibility_Container_proxy* _Myproxy{};_Iterator_base12* _Mynextiter{};
};
#endif // _ITERATOR_DEBUG_LEVEL != 0 定于数组的const迭代器
template <class _Ty, size_t _Size>
class _Array_const_iterator
#if _ITERATOR_DEBUG_LEVEL != 0: private _Iterator_base12_compatible
#endif // _ITERATOR_DEBUG_LEVEL != 0
{
public:
#ifdef __cpp_lib_conceptsusing iterator_concept = contiguous_iterator_tag;
#endif // __cpp_lib_conceptsusing iterator_category = random_access_iterator_tag;using value_type        = _Ty;using difference_type   = ptrdiff_t;using pointer           = const _Ty*;using reference         = const _Ty&;enum { _EEN_SIZE = _Size }; // helper for expression evaluator#if _ITERATOR_DEBUG_LEVEL == 0_CONSTEXPR17 _Array_const_iterator() noexcept : _Ptr() {}_CONSTEXPR17 explicit _Array_const_iterator(pointer _Parg, size_t _Off = 0) noexcept : _Ptr(_Parg + _Off) {}_NODISCARD _CONSTEXPR17 reference operator*() const noexcept {return *_Ptr;}_NODISCARD _CONSTEXPR17 pointer operator->() const noexcept {return _Ptr;}_CONSTEXPR17 _Array_const_iterator& operator++() noexcept {++_Ptr;return *this;}_CONSTEXPR17 _Array_const_iterator operator++(int) noexcept {_Array_const_iterator _Tmp = *this;++_Ptr;return _Tmp;}_CONSTEXPR17 _Array_const_iterator& operator--() noexcept {--_Ptr;return *this;}_CONSTEXPR17 _Array_const_iterator operator--(int) noexcept {_Array_const_iterator _Tmp = *this;--_Ptr;return _Tmp;}_CONSTEXPR17 _Array_const_iterator& operator+=(const ptrdiff_t _Off) noexcept {_Ptr += _Off;return *this;}_NODISCARD _CONSTEXPR17 _Array_const_iterator operator+(const ptrdiff_t _Off) const noexcept {_Array_const_iterator _Tmp = *this;return _Tmp += _Off;}_CONSTEXPR17 _Array_const_iterator& operator-=(const ptrdiff_t _Off) noexcept {_Ptr -= _Off;return *this;}_NODISCARD _CONSTEXPR17 _Array_const_iterator operator-(const ptrdiff_t _Off) const noexcept {_Array_const_iterator _Tmp = *this;return _Tmp -= _Off;}_NODISCARD _CONSTEXPR17 ptrdiff_t operator-(const _Array_const_iterator& _Right) const noexcept {return _Ptr - _Right._Ptr;}_NODISCARD _CONSTEXPR17 reference operator[](const ptrdiff_t _Off) const noexcept {return _Ptr[_Off];}_NODISCARD _CONSTEXPR17 bool operator==(const _Array_const_iterator& _Right) const noexcept {return _Ptr == _Right._Ptr;}#if _HAS_CXX20_NODISCARD constexpr strong_ordering operator<=>(const _Array_const_iterator& _Right) const noexcept {return _Ptr <=> _Right._Ptr;}
#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv_NODISCARD _CONSTEXPR17 bool operator!=(const _Array_const_iterator& _Right) const noexcept {return !(*this == _Right);}_NODISCARD _CONSTEXPR17 bool operator<(const _Array_const_iterator& _Right) const noexcept {return _Ptr < _Right._Ptr;}_NODISCARD _CONSTEXPR17 bool operator>(const _Array_const_iterator& _Right) const noexcept {return _Right < *this;}_NODISCARD _CONSTEXPR17 bool operator<=(const _Array_const_iterator& _Right) const noexcept {return !(_Right < *this);}_NODISCARD _CONSTEXPR17 bool operator>=(const _Array_const_iterator& _Right) const noexcept {return !(*this < _Right);}
#endif // !_HAS_CXX20using _Prevent_inheriting_unwrap = _Array_const_iterator;_NODISCARD constexpr pointer _Unwrapped() const noexcept {return _Ptr;}static constexpr bool _Unwrap_when_unverified = true;constexpr void _Seek_to(pointer _It) noexcept {_Ptr = _It;}private:pointer _Ptr; // beginning of array#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv_CONSTEXPR17 _Array_const_iterator() noexcept : _Ptr(), _Idx(0) {}_CONSTEXPR17 explicit _Array_const_iterator(pointer _Parg, size_t _Off = 0) noexcept : _Ptr(_Parg), _Idx(_Off) {}_NODISCARD _CONSTEXPR17 reference operator*() const noexcept {return *operator->();}_NODISCARD _CONSTEXPR17 pointer operator->() const noexcept {_STL_VERIFY(_Ptr, "cannot dereference value-initialized array iterator");_STL_VERIFY(_Idx < _Size, "cannot dereference out of range array iterator");return _Ptr + _Idx;}_CONSTEXPR17 _Array_const_iterator& operator++() noexcept {_STL_VERIFY(_Ptr, "cannot increment value-initialized array iterator");_STL_VERIFY(_Idx < _Size, "cannot increment array iterator past end");++_Idx;return *this;}_CONSTEXPR17 _Array_const_iterator operator++(int) noexcept {_Array_const_iterator _Tmp = *this;++*this;return _Tmp;}_CONSTEXPR17 _Array_const_iterator& operator--() noexcept {_STL_VERIFY(_Ptr, "cannot decrement value-initialized array iterator");_STL_VERIFY(_Idx != 0, "cannot decrement array iterator before begin");--_Idx;return *this;}_CONSTEXPR17 _Array_const_iterator operator--(int) noexcept {_Array_const_iterator _Tmp = *this;--*this;return _Tmp;}constexpr void _Verify_offset(const ptrdiff_t _Off) const noexcept {if (_Off != 0) {_STL_VERIFY(_Ptr, "cannot seek value-initialized array iterator");}if (_Off < 0) {_STL_VERIFY(_Idx >= size_t{0} - static_cast<size_t>(_Off), "cannot seek array iterator before begin");}if (_Off > 0) {_STL_VERIFY(_Size - _Idx >= static_cast<size_t>(_Off), "cannot seek array iterator after end");}}_CONSTEXPR17 _Array_const_iterator& operator+=(const ptrdiff_t _Off) noexcept {_Verify_offset(_Off);_Idx += static_cast<size_t>(_Off);return *this;}_NODISCARD _CONSTEXPR17 _Array_const_iterator operator+(const ptrdiff_t _Off) const noexcept {_Array_const_iterator _Tmp = *this;return _Tmp += _Off;}_CONSTEXPR17 _Array_const_iterator& operator-=(const ptrdiff_t _Off) noexcept {return *this += -_Off;}_NODISCARD _CONSTEXPR17 _Array_const_iterator operator-(const ptrdiff_t _Off) const noexcept {_Array_const_iterator _Tmp = *this;return _Tmp -= _Off;}_NODISCARD _CONSTEXPR17 ptrdiff_t operator-(const _Array_const_iterator& _Right) const noexcept {_Compat(_Right);return static_cast<ptrdiff_t>(_Idx - _Right._Idx);}_NODISCARD _CONSTEXPR17 reference operator[](const ptrdiff_t _Off) const noexcept {return *(*this + _Off);}_NODISCARD _CONSTEXPR17 bool operator==(const _Array_const_iterator& _Right) const noexcept {_Compat(_Right);return _Idx == _Right._Idx;}#if _HAS_CXX20_NODISCARD constexpr strong_ordering operator<=>(const _Array_const_iterator& _Right) const noexcept {_Compat(_Right);return _Idx <=> _Right._Idx;}
#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv_NODISCARD _CONSTEXPR17 bool operator!=(const _Array_const_iterator& _Right) const noexcept {return !(*this == _Right);}_NODISCARD _CONSTEXPR17 bool operator<(const _Array_const_iterator& _Right) const noexcept {_Compat(_Right);return _Idx < _Right._Idx;}_NODISCARD _CONSTEXPR17 bool operator>(const _Array_const_iterator& _Right) const noexcept {return _Right < *this;}_NODISCARD _CONSTEXPR17 bool operator<=(const _Array_const_iterator& _Right) const noexcept {return !(_Right < *this);}_NODISCARD _CONSTEXPR17 bool operator>=(const _Array_const_iterator& _Right) const noexcept {return !(*this < _Right);}
#endif // !_HAS_CXX20_CONSTEXPR17 void _Compat(const _Array_const_iterator& _Right) const noexcept { // test for compatible iterator pair_STL_VERIFY(_Ptr == _Right._Ptr, "array iterators incompatible");}using _Prevent_inheriting_unwrap = _Array_const_iterator;_NODISCARD constexpr pointer _Unwrapped() const noexcept {return _Ptr + _Idx;}constexpr void _Verify_with(const _Array_const_iterator& _Last) const noexcept {// note _Compat check inside operator<=_STL_VERIFY(*this <= _Last, "array iterator range transposed");}constexpr void _Seek_to(pointer _It) noexcept {_Idx = static_cast<size_t>(_It - _Ptr);}private:pointer _Ptr; // beginning of arraysize_t _Idx; // offset into array
#endif // _ITERATOR_DEBUG_LEVEL == 0
};#if _ITERATOR_DEBUG_LEVEL != 0
template <class _Ty, size_t _Size>
constexpr void _Verify_range(const _Array_const_iterator<_Ty, _Size>& _First, const _Array_const_iterator<_Ty, _Size>& _Last) noexcept {// TRANSITION, CUDA_First._Verify_with(_Last);
}
#endif // _ITERATOR_DEBUG_LEVEL != 0/// 迭代器模板特化
template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR17 _Array_const_iterator<_Ty, _Size> operator+(const ptrdiff_t _Off, _Array_const_iterator<_Ty, _Size> _Next) noexcept {return _Next += _Off;
}#if _HAS_CXX20
template <class _Ty, size_t _Size>
struct pointer_traits<_Array_const_iterator<_Ty, _Size>> {using pointer         = _Array_const_iterator<_Ty, _Size>;using element_type    = const _Ty;using difference_type = ptrdiff_t;_NODISCARD static constexpr element_type* to_address(const pointer _Iter) noexcept {return _Iter._Unwrapped();}
};
#endif // _HAS_CXX20/// 定义子类:非常迭代器
template <class _Ty, size_t _Size>
class _Array_iterator : public _Array_const_iterator<_Ty, _Size> {
public:using _Mybase = _Array_const_iterator<_Ty, _Size>;#ifdef __cpp_lib_conceptsusing iterator_concept = contiguous_iterator_tag;
#endif // __cpp_lib_conceptsusing iterator_category = random_access_iterator_tag;using value_type        = _Ty;using difference_type   = ptrdiff_t;using pointer           = _Ty*;using reference         = _Ty&;enum { _EEN_SIZE = _Size }; // helper for expression evaluator_CONSTEXPR17 _Array_iterator() noexcept {}_CONSTEXPR17 explicit _Array_iterator(pointer _Parg, size_t _Off = 0) noexcept : _Mybase(_Parg, _Off) {}_NODISCARD _CONSTEXPR17 reference operator*() const noexcept {return const_cast<reference>(_Mybase::operator*());}_NODISCARD _CONSTEXPR17 pointer operator->() const noexcept {return const_cast<pointer>(_Mybase::operator->());  // 去常}// 前++ 重载_CONSTEXPR17 _Array_iterator& operator++() noexcept {_Mybase::operator++();return *this;}// 后加加重载_CONSTEXPR17 _Array_iterator operator++(int) noexcept {_Array_iterator _Tmp = *this;_Mybase::operator++();return _Tmp;}// 前减减重载 _CONSTEXPR17 _Array_iterator& operator--() noexcept {_Mybase::operator--();return *this;}// 后减减重载_CONSTEXPR17 _Array_iterator operator--(int) noexcept {_Array_iterator _Tmp = *this;_Mybase::operator--();return _Tmp;}_CONSTEXPR17 _Array_iterator& operator+=(const ptrdiff_t _Off) noexcept {_Mybase::operator+=(_Off);return *this;}_NODISCARD _CONSTEXPR17 _Array_iterator operator+(const ptrdiff_t _Off) const noexcept {_Array_iterator _Tmp = *this;return _Tmp += _Off;}_CONSTEXPR17 _Array_iterator& operator-=(const ptrdiff_t _Off) noexcept {_Mybase::operator-=(_Off);return *this;}using _Mybase::operator-;_NODISCARD _CONSTEXPR17 _Array_iterator operator-(const ptrdiff_t _Off) const noexcept {_Array_iterator _Tmp = *this;return _Tmp -= _Off;}// 下标操作符重载_NODISCARD _CONSTEXPR17 reference operator[](const ptrdiff_t _Off) const noexcept {return const_cast<reference>(_Mybase::operator[](_Off));}using _Prevent_inheriting_unwrap = _Array_iterator;_NODISCARD constexpr pointer _Unwrapped() const noexcept {return const_cast<pointer>(_Mybase::_Unwrapped());}
};template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR17 _Array_iterator<_Ty, _Size> operator+(const ptrdiff_t _Off, _Array_iterator<_Ty, _Size> _Next) noexcept {return _Next += _Off;
}#if _HAS_CXX20
template <class _Ty, size_t _Size>
struct pointer_traits<_Array_iterator<_Ty, _Size>> {using pointer         = _Array_iterator<_Ty, _Size>;using element_type    = _Ty;using difference_type = ptrdiff_t;_NODISCARD static constexpr element_type* to_address(const pointer _Iter) noexcept {return _Iter._Unwrapped();}
};
#endif // _HAS_CXX20/// 定义数组模板
template <class _Ty, size_t _Size>
class array { // fixed size array of values
public:using value_type      = _Ty;using size_type       = size_t;using difference_type = ptrdiff_t;using pointer         = _Ty*;using const_pointer   = const _Ty*;using reference       = _Ty&;using const_reference = const _Ty&;using iterator       = _Array_iterator<_Ty, _Size>;using const_iterator = _Array_const_iterator<_Ty, _Size>;using reverse_iterator       = _STD reverse_iterator<iterator>;using const_reverse_iterator = _STD reverse_iterator<const_iterator>;#if _HAS_TR1_NAMESPACE_DEPRECATE_TR1_NAMESPACE void assign(const _Ty& _Value) {_STD fill_n(_Elems, _Size, _Value);}
#endif // _HAS_TR1_NAMESPACE_CONSTEXPR20 void fill(const _Ty& _Value) {_STD fill_n(_Elems, _Size, _Value);}_CONSTEXPR20 void swap(array& _Other) noexcept(_Is_nothrow_swappable<_Ty>::value) {_Swap_ranges_unchecked(_Elems, _Elems + _Size, _Other._Elems);}_NODISCARD _CONSTEXPR17 iterator begin() noexcept {return iterator(_Elems, 0);}_NODISCARD _CONSTEXPR17 const_iterator begin() const noexcept {return const_iterator(_Elems, 0);}_NODISCARD _CONSTEXPR17 iterator end() noexcept {return iterator(_Elems, _Size);}_NODISCARD _CONSTEXPR17 const_iterator end() const noexcept {return const_iterator(_Elems, _Size);}_NODISCARD _CONSTEXPR17 reverse_iterator rbegin() noexcept {return reverse_iterator(end());}_NODISCARD _CONSTEXPR17 const_reverse_iterator rbegin() const noexcept {return const_reverse_iterator(end());}_NODISCARD _CONSTEXPR17 reverse_iterator rend() noexcept {return reverse_iterator(begin());}_NODISCARD _CONSTEXPR17 const_reverse_iterator rend() const noexcept {return const_reverse_iterator(begin());}_NODISCARD _CONSTEXPR17 const_iterator cbegin() const noexcept {return begin();}_NODISCARD _CONSTEXPR17 const_iterator cend() const noexcept {return end();}_NODISCARD _CONSTEXPR17 const_reverse_iterator crbegin() const noexcept {return rbegin();}_NODISCARD _CONSTEXPR17 const_reverse_iterator crend() const noexcept {return rend();}_CONSTEXPR17 _Ty* _Unchecked_begin() noexcept {return _Elems;}_CONSTEXPR17 const _Ty* _Unchecked_begin() const noexcept {return _Elems;}_CONSTEXPR17 _Ty* _Unchecked_end() noexcept {return _Elems + _Size;}_CONSTEXPR17 const _Ty* _Unchecked_end() const noexcept {return _Elems + _Size;}_NODISCARD constexpr size_type size() const noexcept {return _Size;}_NODISCARD constexpr size_type max_size() const noexcept {return _Size;}_NODISCARD constexpr bool empty() const noexcept {return false;}_NODISCARD _CONSTEXPR17 reference at(size_type _Pos) {if (_Size <= _Pos) {_Xran();}return _Elems[_Pos];}_NODISCARD constexpr const_reference at(size_type _Pos) const {if (_Size <= _Pos) {_Xran();}return _Elems[_Pos];}_NODISCARD _CONSTEXPR17 reference operator[](_In_range_(0, _Size - 1) size_type _Pos) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0_STL_VERIFY(_Pos < _Size, "array subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0return _Elems[_Pos];}_NODISCARD constexpr const_reference operator[](_In_range_(0, _Size - 1) size_type _Pos) const noexcept/* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0_STL_VERIFY(_Pos < _Size, "array subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0return _Elems[_Pos];}_NODISCARD _CONSTEXPR17 reference front() noexcept /* strengthened */ {return _Elems[0];}_NODISCARD constexpr const_reference front() const noexcept /* strengthened */ {return _Elems[0];}_NODISCARD _CONSTEXPR17 reference back() noexcept /* strengthened */ {return _Elems[_Size - 1];}_NODISCARD constexpr const_reference back() const noexcept /* strengthened */ {return _Elems[_Size - 1];}_NODISCARD _CONSTEXPR17 _Ty* data() noexcept {return _Elems;}_NODISCARD _CONSTEXPR17 const _Ty* data() const noexcept {return _Elems;}[[noreturn]] void _Xran() const {_Xout_of_range("invalid array<T, N> subscript");}_Ty _Elems[_Size];
};#if _HAS_CXX17
template <class _First, class... _Rest>
struct _Enforce_same {static_assert(conjunction_v<is_same<_First, _Rest>...>,"N4687 26.3.7.2 [array.cons]/2: ""Requires: (is_same_v<T, U> && ...) is true. Otherwise the program is ill-formed.");using type = _First;
};/// 检查数组中元素类型与第一个要严格一致
template <class _First, class... _Rest>
array(_First, _Rest...) -> array<typename _Enforce_same<_First, _Rest...>::type, 1 + sizeof...(_Rest)>;
#endif // _HAS_CXX17/// 数组模板偏特化
template <class _Ty>
class array<_Ty, 0> {
public:using value_type      = _Ty;using size_type       = size_t;using difference_type = ptrdiff_t;using pointer         = _Ty*;using const_pointer   = const _Ty*;using reference       = _Ty&;using const_reference = const _Ty&;using iterator               = _Array_iterator<_Ty, 0>;using const_iterator         = _Array_const_iterator<_Ty, 0>;using reverse_iterator       = _STD reverse_iterator<iterator>;using const_reverse_iterator = _STD reverse_iterator<const_iterator>;#if _HAS_TR1_NAMESPACE_DEPRECATE_TR1_NAMESPACE void assign(const _Ty&) {}
#endif // _HAS_TR1_NAMESPACE_CONSTEXPR20 void fill(const _Ty&) {}_CONSTEXPR20 void swap(array&) noexcept {}_NODISCARD _CONSTEXPR17 iterator begin() noexcept {return iterator{};}_NODISCARD _CONSTEXPR17 const_iterator begin() const noexcept {return const_iterator{};}_NODISCARD _CONSTEXPR17 iterator end() noexcept {return iterator{};}_NODISCARD _CONSTEXPR17 const_iterator end() const noexcept {return const_iterator{};}_NODISCARD _CONSTEXPR17 reverse_iterator rbegin() noexcept {return reverse_iterator(end());}_NODISCARD _CONSTEXPR17 const_reverse_iterator rbegin() const noexcept {return const_reverse_iterator(end());}_NODISCARD _CONSTEXPR17 reverse_iterator rend() noexcept {return reverse_iterator(begin());}_NODISCARD _CONSTEXPR17 const_reverse_iterator rend() const noexcept {return const_reverse_iterator(begin());}_NODISCARD _CONSTEXPR17 const_iterator cbegin() const noexcept {return begin();}_NODISCARD _CONSTEXPR17 const_iterator cend() const noexcept {return end();}_NODISCARD _CONSTEXPR17 const_reverse_iterator crbegin() const noexcept {return rbegin();}_NODISCARD _CONSTEXPR17 const_reverse_iterator crend() const noexcept {return rend();}_CONSTEXPR17 _Ty* _Unchecked_begin() noexcept {return nullptr;}_CONSTEXPR17 const _Ty* _Unchecked_begin() const noexcept {return nullptr;}_CONSTEXPR17 _Ty* _Unchecked_end() noexcept {return nullptr;}_CONSTEXPR17 const _Ty* _Unchecked_end() const noexcept {return nullptr;}_NODISCARD constexpr size_type size() const noexcept {return 0;}_NODISCARD constexpr size_type max_size() const noexcept {return 0;}_NODISCARD constexpr bool empty() const noexcept {return true;}[[noreturn]] reference at(size_type) {_Xran();}[[noreturn]] const_reference at(size_type) const {_Xran();}_NODISCARD reference operator[](size_type) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0_STL_REPORT_ERROR("array subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0return _Elems[0];}_NODISCARD const_reference operator[](size_type) const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0_STL_REPORT_ERROR("array subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0return _Elems[0];}_NODISCARD reference front() noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0_STL_REPORT_ERROR("array<T, 0>::front() invalid");
#endif // _CONTAINER_DEBUG_LEVEL > 0return _Elems[0];}_NODISCARD const_reference front() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0_STL_REPORT_ERROR("array<T, 0>::front() invalid");
#endif // _CONTAINER_DEBUG_LEVEL > 0return _Elems[0];}_NODISCARD reference back() noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0_STL_REPORT_ERROR("array<T, 0>::back() invalid");
#endif // _CONTAINER_DEBUG_LEVEL > 0return _Elems[0];}_NODISCARD const_reference back() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0_STL_REPORT_ERROR("array<T, 0>::back() invalid");
#endif // _CONTAINER_DEBUG_LEVEL > 0return _Elems[0];}_NODISCARD _CONSTEXPR17 _Ty* data() noexcept {return nullptr;}_NODISCARD _CONSTEXPR17 const _Ty* data() const noexcept {return nullptr;}[[noreturn]] void _Xran() const {_Xout_of_range("invalid array<T, 0> subscript");}_Ty _Elems[1];
};template <class _Ty, size_t _Size, enable_if_t<_Size == 0 || _Is_swappable<_Ty>::value, int> = 0>
_CONSTEXPR20 void swap(array<_Ty, _Size>& _Left, array<_Ty, _Size>& _Right) noexcept(noexcept(_Left.swap(_Right))) {return _Left.swap(_Right);
}template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR20 bool operator==(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {
#ifdef __EDG__ // TRANSITION, VSO-1161663return _STD equal(_Left.begin(), _Left.end(), _Right.begin());
#else // ^^^ workaround / no workaround vvvreturn _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin());
#endif // ^^^ no workaround ^^^
}#if !_HAS_CXX20
template <class _Ty, size_t _Size>
_NODISCARD bool operator!=(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {return !(_Left == _Right);
}
#endif // !_HAS_CXX20#ifdef __cpp_lib_concepts
template <class _Ty, size_t _Size>
_NODISCARD constexpr _Synth_three_way_result<_Ty> operator<=>(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {
#ifdef __EDG__ // TRANSITION, VSO-1161663return _STD lexicographical_compare_three_way(_Left.begin(), _Left.end(), _Right.begin(), _Right.end(), _Synth_three_way{});
#else // ^^^ workaround / no workaround vvvreturn _STD lexicographical_compare_three_way(_Left._Unchecked_begin(), _Left._Unchecked_end(),_Right._Unchecked_begin(), _Right._Unchecked_end(), _Synth_three_way{});
#endif // ^^^ no workaround ^^^
}
#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv
template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR20 bool operator<(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {
#ifdef __EDG__ // TRANSITION, VSO-1161663return _STD lexicographical_compare(_Left.begin(), _Left.end(), _Right.begin(), _Right.end());
#else // ^^^ workaround / no workaround vvvreturn _STD lexicographical_compare(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin(), _Right._Unchecked_end());
#endif // ^^^ no workaround ^^^
}template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR20 bool operator>(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {return _Right < _Left;
}template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR20 bool operator<=(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {return !(_Right < _Left);
}template <class _Ty, size_t _Size>
_NODISCARD _CONSTEXPR20 bool operator>=(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) {return !(_Left < _Right);
}
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^#if _HAS_CXX20
template <class _Ty, size_t _Size, size_t... _Idx>
_NODISCARD constexpr array<remove_cv_t<_Ty>, _Size> _To_array_lvalue_impl(_Ty (&_Array)[_Size], index_sequence<_Idx...>) {return {{_Array[_Idx]...}};
}template <class _Ty, size_t _Size, size_t... _Idx>
_NODISCARD constexpr array<remove_cv_t<_Ty>, _Size> _To_array_rvalue_impl(_Ty(&&_Array)[_Size], index_sequence<_Idx...>) {return {{_STD move(_Array[_Idx])...}};
}template <class _Ty, size_t _Size>
_NODISCARD constexpr array<remove_cv_t<_Ty>, _Size> to_array(_Ty (&_Array)[_Size]) {static_assert(!is_array_v<_Ty>, "N4830 [array.creation]/1: ""to_array does not accept multidimensional arrays.");static_assert(is_constructible_v<_Ty, _Ty&>, "N4830 [array.creation]/1: ""to_array requires copy constructible elements.");return _To_array_lvalue_impl(_Array, make_index_sequence<_Size>{});
}template <class _Ty, size_t _Size>
_NODISCARD constexpr array<remove_cv_t<_Ty>, _Size> to_array(_Ty(&&_Array)[_Size]) {static_assert(!is_array_v<_Ty>, "N4830 [array.creation]/4: ""to_array does not accept multidimensional arrays.");static_assert(is_move_constructible_v<_Ty>, "N4830 [array.creation]/4: ""to_array requires move constructible elements.");return _To_array_rvalue_impl(_STD move(_Array), make_index_sequence<_Size>{});
}
#endif // _HAS_CXX20template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr _Ty& get(array<_Ty, _Size>& _Arr) noexcept {static_assert(_Idx < _Size, "array index out of bounds");return _Arr._Elems[_Idx];
}template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr const _Ty& get(const array<_Ty, _Size>& _Arr) noexcept {static_assert(_Idx < _Size, "array index out of bounds");return _Arr._Elems[_Idx];
}template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr _Ty&& get(array<_Ty, _Size>&& _Arr) noexcept {static_assert(_Idx < _Size, "array index out of bounds");return _STD move(_Arr._Elems[_Idx]);
}template <size_t _Idx, class _Ty, size_t _Size>
_NODISCARD constexpr const _Ty&& get(const array<_Ty, _Size>&& _Arr) noexcept {static_assert(_Idx < _Size, "array index out of bounds");return _STD move(_Arr._Elems[_Idx]);
}#if _HAS_TR1_NAMESPACE
namespace _DEPRECATE_TR1_NAMESPACE tr1 {using _STD array;using _STD get;
} // namespace tr1
#endif // _HAS_TR1_NAMESPACE
_STD_END#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _ARRAY_

从源码来看,非常经典而简洁,在我们平时自己使用元编程技巧时,有不错的借鉴意义。而且这一段难度比较低,基本上大家应该都能看得懂。
std::array 在底层实现上,还是依赖于 基础数组 这一数据类型,以下源码可以佐证。

template <class _Ty, size_t _Size>
class array { // fixed size array of values_Ty _Elems[_Size];  // 数组
};

个人喜欢std::arrayOOP ,不过std::array 也有觉得可以优化的地方,譬如不支持弹性数组的特性,不支持扩容,不支持参数化列表初始化等,不过,这也许正是设计者设计std::array如此简洁优雅之意图。
编程,不只是技术,深入去思考,会觉得简直就是艺术~
在这里插入图片描述

这篇关于STL:std::array 和 基本数组类型array 浅谈一二三的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/539897

相关文章

SQL Server中,查询数据库中有多少个表,以及数据库其余类型数据统计查询

sqlserver查询数据库中有多少个表 sql server 数表:select count(1) from sysobjects where xtype='U'数视图:select count(1) from sysobjects where xtype='V'数存储过程select count(1) from sysobjects where xtype='P' SE

C#中,decimal类型使用

在Microsoft SQL Server中numeric类型,在C#中使用的时候,需要用decimal类型与其对应,不能使用int等类型。 SQL:numeric C#:decimal

C++面试八股文:std::deque用过吗?

100编程书屋_孔夫子旧书网 某日二师兄参加XXX科技公司的C++工程师开发岗位第26面: 面试官:deque用过吗? 二师兄:说实话,很少用,基本没用过。 面试官:为什么? 二师兄:因为使用它的场景很少,大部分需要性能、且需要自动扩容的时候使用vector,需要随机插入和删除的时候可以使用list。 面试官:那你知道STL中的stack是如何实现的吗? 二师兄:默认情况下,stack使

微信小程序开发必知必会:文件结构和基本配置

一、微信小程序基本文件结构 1.  project.config.json:项目的基本配置文件,包括项目名称、appid、项目目录、页面文件夹等。     {"setting": {"urlCheck": false,"es6": true,"postcss": true,"nodeModulesPath": "D:\\\\node_modules"},"appid": "wxd678e

说一说三大运营商的流量类型,看完就知道该怎么选运营商了!

说一说三大运营商的流量类型,看完就知道该怎么选运营商了?目前三大运营商的流量类型大致分为通用流量和定向流量,比如: 中国电信:通用流量+定向流量 电信推出的套餐通常由通用流量+定向流量所组成,通用流量比较多,一般都在100G以上,而且电信套餐长期套餐较多,大多无合约期,自主激活的卡也是最多的,适合没有通话需求的朋友办理。 中国移动:通用流量+定向流量 移动推出的套餐通常由通用流量+定向

【杂记-浅谈DHCP动态主机配置协议】

DHCP动态主机配置协议 一、DHCP概述1、定义2、作用3、报文类型 二、DHCP的工作原理三、DHCP服务器的配置和管理 一、DHCP概述 1、定义 DHCP,Dynamic Host Configuration Protocol,动态主机配置协议,是一种网络协议,主要用于在IP网络中自动分配和管理IP地址以及其他网络配置参数。 2、作用 DHCP允许计算机和其他设备通

剑指offer(C++)--数组中只出现一次的数字

题目 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 class Solution {public:void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {int len = data.size();if(len<2)return;int one = 0;for(int i

浅谈 MySQL for excel

欢迎关注微信公众号“Python生态智联”  MySQL for excel是一个大小只有几兆的MySQL附件,它能让我们在Microsoft excel中处理MySQL数据。小编用了两天时间浏览了MySQL for excel的使用指南并按demo演示了一遍(手册地址https://dev.mysql.com/doc/mysql-for-excel/en/),现从功能和局限两方面对MySQL

PHP的基本语法有哪些?

PHP的基本语法包括以下几个方面: PHP标记:PHP脚本以<?php开始,以?>结束。这是PHP文件的默认文件扩展名是.php。 变量和常量:变量以$符号开头,其后是变量的名称。常量使用define()函数定义,例如define("常量名", 常量值);。 数据类型:PHP支持多种数据类型,如整型、浮点型、字符串型等。 注释:PHP支持单行注释(用//表示)和多行注释(用/* */表示

微服务中RPC的强类型检查与HTTP的弱类型对比

在微服务架构中,服务间的通信是一个至关重要的环节。其中,远程过程调用(RPC)和HTTP是两种最常见的通信方式。虽然它们都能实现服务间的数据交换,但在类型检查方面,RPC的强类型检查和HTTP的弱类型之间有着显著的差异。本文将深入探讨这两种通信方式在类型检查方面的优缺点,以及它们对微服务架构的影响。 一、RPC的强类型检查 RPC的强类型检查是其核心优势之一。在RPC通信中,客户端和服务端都使