C++的三个数组模板类

来源:互联网 发布:用js做轮播图 编辑:程序博客网 时间:2024/06/15 03:49


valarray

valarray类是由头文件valarray支持的。顾名思义,这个类用于处理数值(或具有类似特性的类),它支持诸如将数组中所有元素的值相加以及在数组中找出最大和最小的值等操作。valarray被定义为一个模板类,以便能够处理不同的数据类型。


特点及使用方法

valarray的接口定义如下:

template <typename T>class valarray{public:    typedef T value_type;        // 构造和析构    valarray();    explicit valarray(size_t);    valarray(const T&, size_t);    valarray(const T*, size_t);    valarray(const valarray&);    valarray(const slice_array<T>&);    valarray(const gslice_array<T>&);    valarray(const mask_array<T>&);    valarray(const indirect_array<T>&);    ~valarray();        // 赋值    valarray<T>& operator=(const valarray<T>&);    valarray<T>& operator=(const T&); // 赋给所有元素    valarray<T>& operator=(const slice_array<T>&);    valarray<T>& operator=(const gslice_array<T>&);    valarray<T>& operator=(const mask_array<T>&);    valarray<T>& operator=(const indirect_array<T>&);        // 下标访问    const T&          operator[](size_t) const;    T&                operator[](size_t);    valarray<T>       operator[](slice) const;    slice_array<T>    operator[](slice);    valarray<T>       operator[](const gslice&) const;    gslice_array<T>   operator[](const gslice&);    valarray<T>       operator[](const valarray<bool>&) const;    mask_array<T>     operator[](const valarray<bool>&);    valarray<T>       operator[](const valarray<size_t>&) const;    indirect_array<T> operator[](const valarray<size_t>&);        // 运算符, 其他未列出    valarray<T>& operator*= (const T&);    valarray<T>& operator*= (const valarray<T>&);        // member functions    size_t size() const;    T    sum() const;    T    min() const;    T    max() const;    void resize(size_t size, T c = T());        // 移位, 正数左移, 负数右移    valarray<T> shift (int) const;    valarray<T> cshift(int) const; // 循环移位        // 对所有元素执行func函数    valarray<T> apply (T func(T)) const;    valarray<T> apply (T func(const T&)) const;    private:    size_t _M_size;    T* _M_data;};

另外,头文件valarray还将cmath里的大多部分数学函数都进行了重载,使之可应用于valarrayvalarray直接调用operator new()来获取内存,用operator delete()释放内存,所以模板参数里并没有空间配置器。

valarray接口定义中可以得出valarray的一些特点及使用方法:

模板特性意味着声明对象时,必须指定具体的数据类型。因此,使用valarray类来声明一个对象时,需要在标识符valarray后面加上一对尖括号,并在其中包含所需的数据类型。

valarray<int> q_values;valarray<double> weights;

可以创建长度为零的空数组、指定长度的空数组、所有元素被初始化为指定值的数组、用常规数组中的值进行初始化的数组。在C++11中也可以使用初始化列表。

#include <iostream>#include <valarray>int main (void){    using std::valarray;    using std::cout;    using std::endl;    double gpa[5] = {3.1, 3.5, 3.8, 2.9, 3.3};    valarray<double> v1;//长度为0的空数组    valarray<int> v2;//长度为8的空数组(数组元素未初始化)    valarray<int> v3(10, 8);//长度为8,数组元素均被初始化为10    valarray<double> v4(gpa, 4);//长度为4,每一个数组元素都是一个gpa数组,但v4与二维数组不同    cout << v4[1] << " " << v4[2] << endl;    valarray<int> v5 = {20, 32, 17, 9};    return 0;}

一段源代码介绍valarray最常用的几种用法


#include <iostream>#include <valarray>int main (void){    using std::valarray;    using std::cout;    using std::endl;    valarray<int> v = {-1, -8, 0, 20, 32, 17, 9};    cout << "数组元素:" << v[0] << " " << v[1] << " " << v[2] << " " << v[3] << " " << v[4] << " " << v[5] << " " << v[6] << endl;    cout << "长度:" << v.size() << endl;    cout << "最大值:" << v.max() << endl;    cout << "最小值:" << v.min() << endl;    cout << "数组求和结果:" << v.sum() << endl << endl;    v.resize(5);//重新设置数组大小,并对其进行初始化(默认为0)    v = {3, -8, 24, 0, -1};    cout << "重设长度后:" << endl;    cout << "数组元素:" << v[0] << " " << v[1] << " " << v[2] << " " << v[3] << " " << v[4] << endl;    cout << "长度:" << v.size() << endl;    cout << "最大值:" << v.max() << endl;    cout << "最小值:" << v.min() << endl;    cout << "数组求和结果:" << v.sum() << endl;    return 0;}

此外valarray还有一些不常见但在数学领域中也很实用的成员函数的声明:

1.v.apply(<value_type (*__f)(value_type)>) constvalarray数组的每一个值都用apply所接收到的函数进行计算;

2.v.shift(<int __i>) constvalarray数组移动,参数为正者左移,为负者右移,移动后由0填充剩余位;

3.v.cshift(<int __i>) constvalarray数组的数据进行循环移动,参数为正这左移,为负者右移。


C++还有slice类和Gslice类,主要用来配合valarray类使用。


vector

在计算中,矢量(vector)对应数组,而不是数学矢量(在数学中,可以使用N个分量来表示N维数学矢量,因此从这方面讲,数学矢量类似一个N维数组。然而,数学矢量还有一些计算机矢量不具备的其他特征,如内乘积和外乘积)。计算矢量存储了一组可随机访问的值,即可以使用索引来直接访问矢量的第10个元素,而不必首先访问第9个元素。所以vector类提供了与valarray和array类似的操作,即可以创建vector对象,将一个vector对象赋给另一个对象,使用[]运算符来访问vector元素。

特点及使用方法

vector头文件的部分声明如下

namespace std{template <class T, class Allocator = allocator<T> >class vector{public:    typedef T                                        value_type;    typedef Allocator                                allocator_type;    typedef typename allocator_type::reference       reference;    typedef typename allocator_type::const_reference const_reference;    typedef implementation-defined                   iterator;    typedef implementation-defined                   const_iterator;    typedef typename allocator_type::size_type       size_type;    typedef typename allocator_type::difference_type difference_type;    typedef typename allocator_type::pointer         pointer;    typedef typename allocator_type::const_pointer   const_pointer;    typedef std::reverse_iterator<iterator>          reverse_iterator;    typedef std::reverse_iterator<const_iterator>    const_reverse_iterator;    vector()        noexcept(is_nothrow_default_constructible<allocator_type>::value);    explicit vector(const allocator_type&);    explicit vector(size_type n);    explicit vector(size_type n, const allocator_type&); // C++14    vector(size_type n, const value_type& value, const allocator_type& = allocator_type());    template <class InputIterator>        vector(InputIterator first, InputIterator last, const allocator_type& = allocator_type());    vector(const vector& x);    vector(vector&& x)        noexcept(is_nothrow_move_constructible<allocator_type>::value);    vector(initializer_list<value_type> il);    vector(initializer_list<value_type> il, const allocator_type& a);    ~vector();    vector& operator=(const vector& x);    vector& operator=(vector&& x)        noexcept(             allocator_type::propagate_on_container_move_assignment::value &&             is_nothrow_move_assignable<allocator_type>::value);    vector& operator=(initializer_list<value_type> il);    template <class InputIterator>        void assign(InputIterator first, InputIterator last);    void assign(size_type n, const value_type& u);    void assign(initializer_list<value_type> il);    allocator_type get_allocator() const noexcept;    iterator               begin() noexcept;    const_iterator         begin()   const noexcept;    iterator               end() noexcept;    const_iterator         end()     const noexcept;    reverse_iterator       rbegin() noexcept;    const_reverse_iterator rbegin()  const noexcept;    reverse_iterator       rend() noexcept;    const_reverse_iterator rend()    const noexcept;    const_iterator         cbegin()  const noexcept;    const_iterator         cend()    const noexcept;    const_reverse_iterator crbegin() const noexcept;    const_reverse_iterator crend()   const noexcept;    size_type size() const noexcept;    size_type max_size() const noexcept;    size_type capacity() const noexcept;    bool empty() const noexcept;    void reserve(size_type n);    void shrink_to_fit() noexcept;    reference       operator[](size_type n);    const_reference operator[](size_type n) const;    reference       at(size_type n);    const_reference at(size_type n) const;    reference       front();    const_reference front() const;    reference       back();    const_reference back() const;    value_type*       data() noexcept;    const value_type* data() const noexcept;    void push_back(const value_type& x);    void push_back(value_type&& x);    template <class... Args>        void emplace_back(Args&&... args);    void pop_back();    template <class... Args> iterator emplace(const_iterator position, Args&&... args);    iterator insert(const_iterator position, const value_type& x);    iterator insert(const_iterator position, value_type&& x);    iterator insert(const_iterator position, size_type n, const value_type& x);    template <class InputIterator>        iterator insert(const_iterator position, InputIterator first, InputIterator last);    iterator insert(const_iterator position, initializer_list<value_type> il);    iterator erase(const_iterator position);    iterator erase(const_iterator first, const_iterator last);    void clear() noexcept;    void resize(size_type sz);    void resize(size_type sz, const value_type& c);    void swap(vector&)        noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||                 allocator_traits<allocator_type>::is_always_equal::value);  // C++17    bool __invariants() const;};template <class Allocator = allocator<T> >class vector<bool, Allocator>{public:    typedef bool                                     value_type;    typedef Allocator                                allocator_type;    typedef implementation-defined                   iterator;    typedef implementation-defined                   const_iterator;    typedef typename allocator_type::size_type       size_type;    typedef typename allocator_type::difference_type difference_type;    typedef iterator                                 pointer;    typedef const_iterator                           const_pointer;    typedef std::reverse_iterator<iterator>          reverse_iterator;    typedef std::reverse_iterator<const_iterator>    const_reverse_iterator;    class reference    {    public:        reference(const reference&) noexcept;        operator bool() const noexcept;        reference& operator=(const bool x) noexcept;        reference& operator=(const reference& x) noexcept;        iterator operator&() const noexcept;        void flip() noexcept;    };    class const_reference    {    public:        const_reference(const reference&) noexcept;        operator bool() const noexcept;        const_iterator operator&() const noexcept;    };    vector()        noexcept(is_nothrow_default_constructible<allocator_type>::value);    explicit vector(const allocator_type&);    explicit vector(size_type n, const allocator_type& a = allocator_type()); // C++14    vector(size_type n, const value_type& value, const allocator_type& = allocator_type());    template <class InputIterator>        vector(InputIterator first, InputIterator last, const allocator_type& = allocator_type());    vector(const vector& x);    vector(vector&& x)        noexcept(is_nothrow_move_constructible<allocator_type>::value);    vector(initializer_list<value_type> il);    vector(initializer_list<value_type> il, const allocator_type& a);    ~vector();    vector& operator=(const vector& x);    vector& operator=(vector&& x)        noexcept(             allocator_type::propagate_on_container_move_assignment::value &&             is_nothrow_move_assignable<allocator_type>::value);    vector& operator=(initializer_list<value_type> il);    template <class InputIterator>        void assign(InputIterator first, InputIterator last);    void assign(size_type n, const value_type& u);    void assign(initializer_list<value_type> il);    allocator_type get_allocator() const noexcept;    iterator               begin() noexcept;    const_iterator         begin()   const noexcept;    iterator               end() noexcept;    const_iterator         end()     const noexcept;    reverse_iterator       rbegin() noexcept;    const_reverse_iterator rbegin()  const noexcept;    reverse_iterator       rend() noexcept;    const_reverse_iterator rend()    const noexcept;    const_iterator         cbegin()  const noexcept;    const_iterator         cend()    const noexcept;    const_reverse_iterator crbegin() const noexcept;    const_reverse_iterator crend()   const noexcept;    size_type size() const noexcept;    size_type max_size() const noexcept;    size_type capacity() const noexcept;    bool empty() const noexcept;    void reserve(size_type n);    void shrink_to_fit() noexcept;    reference       operator[](size_type n);    const_reference operator[](size_type n) const;    reference       at(size_type n);    const_reference at(size_type n) const;    reference       front();    const_reference front() const;    reference       back();    const_reference back() const;    void push_back(const value_type& x);    template <class... Args> void emplace_back(Args&&... args);  // C++14    void pop_back();    template <class... Args> iterator emplace(const_iterator position, Args&&... args);  // C++14    iterator insert(const_iterator position, const value_type& x);    iterator insert(const_iterator position, size_type n, const value_type& x);    template <class InputIterator>        iterator insert(const_iterator position, InputIterator first, InputIterator last);    iterator insert(const_iterator position, initializer_list<value_type> il);    iterator erase(const_iterator position);    iterator erase(const_iterator first, const_iterator last);    void clear() noexcept;    void resize(size_type sz);    void resize(size_type sz, value_type x);    void swap(vector&)        noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||                 allocator_traits<allocator_type>::is_always_equal::value);  // C++17    void flip() noexcept;    bool __invariants() const;};template <class Allocator> struct hash<std::vector<bool, Allocator>>;template <class T, class Allocator> bool operator==(const vector<T,Allocator>& x, const vector<T,Allocator>& y);template <class T, class Allocator> bool operator< (const vector<T,Allocator>& x, const vector<T,Allocator>& y);template <class T, class Allocator> bool operator!=(const vector<T,Allocator>& x, const vector<T,Allocator>& y);template <class T, class Allocator> bool operator> (const vector<T,Allocator>& x, const vector<T,Allocator>& y);template <class T, class Allocator> bool operator>=(const vector<T,Allocator>& x, const vector<T,Allocator>& y);template <class T, class Allocator> bool operator<=(const vector<T,Allocator>& x, const vector<T,Allocator>& y);template <class T, class Allocator>void swap(vector<T,Allocator>& x, vector<T,Allocator>& y)    noexcept(noexcept(x.swap(y)));}

vector是一种容器,属于STL,其功能较valarray和array要更广泛。vector类在STL中,又属于容器类,可以和迭代器一同使用,所以方法众多,有诸如begin()、end()、rbegin()、rend()、capacity()、for_each()、rend()等等与其他STL类共有vector类独有的。详细内容在容器类和STL中会有写。


array

模板类array是传统数组的替代品,比传统数组更安全和方便,虽然功能上不如vector类那么多,但效率相较vector类要高,可以说array更接近于传统数组。

特点及使用方法

array类的定义如下

template <class _Tp, size_t _Size>struct _LIBCPP_TYPE_VIS_ONLY array{    // types:    typedef array __self;    typedef _Tp                                   value_type;    typedef value_type&                           reference;    typedef const value_type&                     const_reference;    typedef value_type*                           iterator;    typedef const value_type*                     const_iterator;    typedef value_type*                           pointer;    typedef const value_type*                     const_pointer;    typedef size_t                                size_type;    typedef ptrdiff_t                             difference_type;    typedef std::reverse_iterator<iterator>       reverse_iterator;    typedef std::reverse_iterator<const_iterator> const_reverse_iterator;    value_type __elems_[_Size > 0 ? _Size : 1];    // No explicit construct/copy/destroy for aggregate type    _LIBCPP_INLINE_VISIBILITY void fill(const value_type& __u)        {_VSTD::fill_n(__elems_, _Size, __u);}    _LIBCPP_INLINE_VISIBILITY    void swap(array& __a) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)        {_VSTD::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);}    // iterators:    _LIBCPP_INLINE_VISIBILITY    iterator begin() _NOEXCEPT {return iterator(__elems_);}    _LIBCPP_INLINE_VISIBILITY    const_iterator begin() const _NOEXCEPT {return const_iterator(__elems_);}    _LIBCPP_INLINE_VISIBILITY    iterator end() _NOEXCEPT {return iterator(__elems_ + _Size);}    _LIBCPP_INLINE_VISIBILITY    const_iterator end() const _NOEXCEPT {return const_iterator(__elems_ + _Size);}    _LIBCPP_INLINE_VISIBILITY    reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());}    _LIBCPP_INLINE_VISIBILITY    const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());}    _LIBCPP_INLINE_VISIBILITY    reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());}    _LIBCPP_INLINE_VISIBILITY    const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());}    _LIBCPP_INLINE_VISIBILITY    const_iterator cbegin() const _NOEXCEPT {return begin();}    _LIBCPP_INLINE_VISIBILITY    const_iterator cend() const _NOEXCEPT {return end();}    _LIBCPP_INLINE_VISIBILITY    const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();}    _LIBCPP_INLINE_VISIBILITY    const_reverse_iterator crend() const _NOEXCEPT {return rend();}    // capacity:    _LIBCPP_INLINE_VISIBILITY    _LIBCPP_CONSTEXPR size_type size() const _NOEXCEPT {return _Size;}    _LIBCPP_INLINE_VISIBILITY    _LIBCPP_CONSTEXPR size_type max_size() const _NOEXCEPT {return _Size;}    _LIBCPP_INLINE_VISIBILITY    _LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT {return _Size == 0;}    // element access:    _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n)             {return __elems_[__n];}    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference operator[](size_type __n) const {return __elems_[__n];}    reference at(size_type __n);    _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference at(size_type __n) const;    _LIBCPP_INLINE_VISIBILITY reference front()             {return __elems_[0];}    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference front() const {return __elems_[0];}    _LIBCPP_INLINE_VISIBILITY reference back()              {return __elems_[_Size > 0 ? _Size-1 : 0];}    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference back() const  {return __elems_[_Size > 0 ? _Size-1 : 0];}    _LIBCPP_INLINE_VISIBILITY    value_type* data() _NOEXCEPT {return __elems_;}    _LIBCPP_INLINE_VISIBILITY    const value_type* data() const _NOEXCEPT {return __elems_;}};

从array类头文件可以总结出array类的几种简单用法

array类的定义(实例化)与vector类有所不同:

array<int, 4> a = {3, -1, 24, 8};array<array<double, 2>, 3> aa = {1.0, 2.3, 2.4, 24.8, 8.24, 10.33};//用array类创建二维数组

创建好后,就可以使用标准数组表示法来访问各个元素。对于多个数组之间的相互复制,标准数组只能逐元素复制,而array类可以直接进行复制(vector类也一样),因为对象之间的相互复制是有定义的。


三个数组模板的区别

vectorvalarrayarray是由不同的小组开发的,用于不同的目的。vector模板类是一个容器类和算法系统的一部分,它支持面向容器的操作,如排序、插入、重新排列、搜索、将数据转移到其他容器中等。而valarray类模板时面向数值计算的,不是STL的一部分。例如,它没有push_back()insert()方法,但为很多数学运算提供了一个简单、直观的接口。最后,array是为替代内置数组而设计的,它通过提供更好、更安全的接口,让数组更紧凑,效率更高。Array表示长度固定的数组,因此不支持push_back()insert(),但提供了多个STL方法,包括begin()end()rgegin()rend(),这使得很容易将STL算法用于array对象。

总而言之,每一个数组模板类都有其特点及其特定应用。valarray类对于数值的各种处理方法以及结合各种数学函数的特点使其在数学编程领域有着重要作用;vector类是三个数组模板类中功能覆盖最全,也最为常用的模板类;而array类是在对传统数组的安全性、方便性进行了相较于另两者简单的改进,其效率较高,可用于一般使用。



本文部分内容摘自《C++ Primer Plus(中文版)第6版》





原创粉丝点击