当前位置: 首页 > 工具软件 > Androidutils > 使用案例 >

Android Utils 之 Vector 学习笔记(三)—— Vector 与 SortedVector 代码分析

严曜文
2023-12-01

实际上在 VectorSortedVector 这两个类中,没有太多内容,主要提供了一些给外部调用的接口而已。不过也有一些需要注意的内容,比如抽象类中的纯虚函数的实现,以及自定义的比较函数等等。


相关文章


Vector

Vectoc 类继承自 VectorImpl,它的大部分功能都是通过直接内部调用父类的函数来实现的。因此这个类的结构与实现都非常简单,以至于只需要一个头文件就能全部包含。

根据代码中的注释可以知道,这一主模板 Vector 类在使用 VectorImpl 时确保了类型安全性。这个类是开放给用户使用的。这个 Vector 和标准模板库中的那个用途应该是一样的,不过在实现上应该有所不同,具体差异其实不必深究,能用就行……

类定义

文件路径:system\core\libutils\include\utils\Vector.h

代码解释:

  • 第 2 行:声明了 SortedVector 类,因为此处没有引用相应的头文件,但后面在构造函数中会用到它。
  • 第 11 行:注意此处用的是私有继承
  • 第 36~133 行:这里全是关于增、删、查找这类的基本操作的调用接口,通过函数名就可以很好地知道它的功能,如果有不清楚的地方,可以看相应函数的注释,都解释得很清楚了。
  • 第 139~143 行:声明了两个函数指针,用于指向自定义的比较函数。排序函数则负责基于比较函数对 Vector 进行排序(排序具体实现在父类中,根据前两章的分析可以知道,用的是插入排序算法)。
  • 第 153~167 行:这里声明的函数以及迭代器 iterator 是为了在一定程度上兼容 STL 中的 Vector 类。用过 STL 中的 Vector 的人应该比较熟悉这些操作了,主要就是基于 iterator 来对 Vector 中元素进行访问、控制、遍历等(注意使用 const_iterator 时不能对元素内容进行操作)。
  • 第 170~176 行:这些是父类中的纯虚函数,此处必须给出相应的具体实现。
template <typename TYPE>
class SortedVector;

/*!
 * The main templated vector class ensuring type safety
 * while making use of VectorImpl.
 * This is the class users want to use.
 */

template <class TYPE>
class Vector : private VectorImpl
{
public:
            typedef TYPE    value_type;

    /*!
     * Constructors and destructors
     */

                            Vector();
                            Vector(const Vector<TYPE>& rhs);
    explicit                Vector(const SortedVector<TYPE>& rhs);
    virtual                 ~Vector();

    /*! copy operator */
            const Vector<TYPE>&     operator = (const Vector<TYPE>& rhs) const;
            Vector<TYPE>&           operator = (const Vector<TYPE>& rhs);

            const Vector<TYPE>&     operator = (const SortedVector<TYPE>& rhs) const;
            Vector<TYPE>&           operator = (const SortedVector<TYPE>& rhs);

            /*
     * empty the vector
     */

    inline  void            clear()             { VectorImpl::clear(); }

    /*!
     * vector stats
     */

    //! returns number of items in the vector
    inline  size_t          size() const                { return VectorImpl::size(); }
    //! returns whether or not the vector is empty
    inline  bool            isEmpty() const             { return VectorImpl::isEmpty(); }
    //! returns how many items can be stored without reallocating the backing store
    inline  size_t          capacity() const            { return VectorImpl::capacity(); }
    //! sets the capacity. capacity can never be reduced less than size()
    inline  ssize_t         setCapacity(size_t size)    { return VectorImpl::setCapacity(size); }

    /*!
     * set the size of the vector. items are appended with the default
     * constructor, or removed from the end as needed.
     */
    inline  ssize_t         resize(size_t size)         { return VectorImpl::resize(size); }

    /*!
     * C-style array access
     */

    //! read-only C-style access
    inline  const TYPE*     array() const;
    //! read-write C-style access
            TYPE*           editArray();

    /*!
     * accessors
     */

    //! read-only access to an item at a given index
    inline  const TYPE&     operator [] (size_t index) const;
    //! alternate name for operator []
    inline  const TYPE&     itemAt(size_t index) const;
    //! stack-usage of the vector. returns the top of the stack (last element)
            const TYPE&     top() const;

    /*!
     * modifying the array
     */

    //! copy-on write support, grants write access to an item
            TYPE&           editItemAt(size_t index);
    //! grants right access to the top of the stack (last element)
            TYPE&           editTop();

            /*!
             * append/insert another vector
             */

    //! insert another vector at a given index
            ssize_t         insertVectorAt(const Vector<TYPE>& vector, size_t index);

    //! append another vector at the end of this one
            ssize_t         appendVector(const Vector<TYPE>& vector);


    //! insert an array at a given index
            ssize_t         insertArrayAt(const TYPE* array, size_t index, size_t length);

    //! append an array at the end of this vector
            ssize_t         appendArray(const TYPE* array, size_t length);

            /*!
             * add/insert/replace items
             */

    //! insert one or several items initialized with their default constructor
    inline  ssize_t         insertAt(size_t index, size_t numItems = 1);
    //! insert one or several items initialized from a prototype item
            ssize_t         insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1);
    //! pop the top of the stack (removes the last element). No-op if the stack's empty
    inline  void            pop();
    //! pushes an item initialized with its default constructor
    inline  void            push();
    //! pushes an item on the top of the stack
            void            push(const TYPE& item);
    //! same as push() but returns the index the item was added at (or an error)
    inline  ssize_t         add();
    //! same as push() but returns the index the item was added at (or an error)
            ssize_t         add(const TYPE& item);
    //! replace an item with a new one initialized with its default constructor
    inline  ssize_t         replaceAt(size_t index);
    //! replace an item with a new one
            ssize_t         replaceAt(const TYPE& item, size_t index);

    /*!
     * remove items
     */

    //! remove several items
    inline  ssize_t         removeItemsAt(size_t index, size_t count = 1);
    //! remove one item
    inline  ssize_t         removeAt(size_t index)  { return removeItemsAt(index); }

    /*!
     * sort (stable) the array
     */

     typedef int (*compar_t)(const TYPE* lhs, const TYPE* rhs);
     typedef int (*compar_r_t)(const TYPE* lhs, const TYPE* rhs, void* state);

     inline status_t        sort(compar_t cmp);
     inline status_t        sort(compar_r_t cmp, void* state);

     // for debugging only
     inline size_t getItemSize() const { return itemSize(); }


     /*
      * these inlines add some level of compatibility with STL. eventually
      * we should probably turn things around.
      */
     typedef TYPE* iterator;
     typedef TYPE const* const_iterator;

     inline iterator begin() { return editArray(); }
     inline iterator end()   { return editArray() + size(); }
     inline const_iterator begin() const { return array(); }
     inline const_iterator end() const   { return array() + size(); }
     inline void reserve(size_t n) { setCapacity(n); }
     inline bool empty() const{ return isEmpty(); }
     inline void push_back(const TYPE& item)  { insertAt(item, size(), 1); }
     inline void push_front(const TYPE& item) { insertAt(item, 0, 1); }
     inline iterator erase(iterator pos) {
         ssize_t index = removeItemsAt(static_cast<size_t>(pos-array()));
         return begin() + index;
     }

protected:
    virtual void    do_construct(void* storage, size_t num) const;
    virtual void    do_destroy(void* storage, size_t num) const;
    virtual void    do_copy(void* dest, const void* from, size_t num) const;
    virtual void    do_splat(void* dest, const void* item, size_t num) const;
    virtual void    do_move_forward(void* dest, const void* from, size_t num) const;
    virtual void    do_move_backward(void* dest, const void* from, size_t num) const;
};

具体实现

文件路径:system\core\libutils\include\utils\Vector.h

Vector 类中大部分函数都是直接调用相应的父类函数进行实现的。但有几个例外,就是父类中的那几个纯虚函数,需要在此进行具体实现。我们可以先看看对应的代码。

template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_construct(void* storage, size_t num) const {
    construct_type( reinterpret_cast<TYPE*>(storage), num );
}

template<class TYPE>
void Vector<TYPE>::do_destroy(void* storage, size_t num) const {
    destroy_type( reinterpret_cast<TYPE*>(storage), num );
}

template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
    copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}

template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
    splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
}

template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
    move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}

template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
    move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}

观察代码,可以注意到,这些函数都直接调用了某些函数(但非父类中实现的函数)来实现相应的功能。这些函数都是在 TypeHelpers.h 中具体实现的,这不在学习范围之内,不过可以看看其中一些具体实现是怎样的。

比如 do_splat 中用到的 splat_type

  • 第 3~8 行:非 trivial 类型的 copy 操作,从 where 位置开始,依次构造 n 个元素空间(并且是调用拷贝构造函数,拷贝对象是 what 指向的元素)。
  • 第 9~14 行:trivial 类型的 copy 操作,则直接从 where 位置开始,依次赋值为 what 指向的元素,共赋值 n 次。
template<typename TYPE> inline
void splat_type(TYPE* where, const TYPE* what, size_t n) {
    if (!traits<TYPE>::has_trivial_copy) {
        while (n > 0) {
            n--;
            new(where) TYPE(*what);
            where++;
        }
    } else {
        while (n > 0) {
            n--;
            *where++ = *what;
        }
    }
}

TypeHelpers.h 中都是类似的,非常底层的实现,这个头文件中将这些操作都封装了起来,简化了其它类的实现代码,同时也使得这些代码更易于阅读。


SortedVector

Vector 不同,SortedVector 继承自 SortedVectorImpl

虽然它们有一个共同的先代(VectorImpl),但很明显,SortedVector 是一个总能保持元素按照指定顺序排列的向量,而 Vector 则需要调用其内置的 sort 函数才能使得元素有序。

类定义

文件路径:system\core\libutils\include\utils\SortedVector.h

这部分与 Vector 类基本一致,先是一些基本操作(此处多了 merge 函数),然后是为了与 STL 减容而给出的关于 iterator 的相关操作,最后就是父类中的纯虚函数(注意这里多了一个 do_compare)。

template <class TYPE>
class SortedVector : private SortedVectorImpl
{
    friend class Vector<TYPE>;

public:
            typedef TYPE    value_type;

    /*!
     * Constructors and destructors
     */

                            SortedVector();
                            SortedVector(const SortedVector<TYPE>& rhs);
    virtual                 ~SortedVector();

    /*! copy operator */
    const SortedVector<TYPE>&   operator = (const SortedVector<TYPE>& rhs) const;
    SortedVector<TYPE>&         operator = (const SortedVector<TYPE>& rhs);

    /*
     * empty the vector
     */

    inline  void            clear()             { VectorImpl::clear(); }

    /*!
     * vector stats
     */

    //! returns number of items in the vector
    inline  size_t          size() const                { return VectorImpl::size(); }
    //! returns whether or not the vector is empty
    inline  bool            isEmpty() const             { return VectorImpl::isEmpty(); }
    //! returns how many items can be stored without reallocating the backing store
    inline  size_t          capacity() const            { return VectorImpl::capacity(); }
    //! sets the capacity. capacity can never be reduced less than size()
    inline  ssize_t         setCapacity(size_t size)    { return VectorImpl::setCapacity(size); }

    /*!
     * C-style array access
     */

    //! read-only C-style access
    inline  const TYPE*     array() const;

    //! read-write C-style access. BE VERY CAREFUL when modifying the array
    //! you must keep it sorted! You usually don't use this function.
            TYPE*           editArray();

            //! finds the index of an item
            ssize_t         indexOf(const TYPE& item) const;

            //! finds where this item should be inserted
            size_t          orderOf(const TYPE& item) const;


    /*!
     * accessors
     */

    //! read-only access to an item at a given index
    inline  const TYPE&     operator [] (size_t index) const;
    //! alternate name for operator []
    inline  const TYPE&     itemAt(size_t index) const;
    //! stack-usage of the vector. returns the top of the stack (last element)
            const TYPE&     top() const;

    /*!
     * modifying the array
     */

            //! add an item in the right place (and replace the one that is there)
            ssize_t         add(const TYPE& item);

            //! editItemAt() MUST NOT change the order of this item
            TYPE&           editItemAt(size_t index) {
                return *( static_cast<TYPE *>(VectorImpl::editItemLocation(index)) );
            }

            //! merges a vector into this one
            ssize_t         merge(const Vector<TYPE>& vector);
            ssize_t         merge(const SortedVector<TYPE>& vector);

            //! removes an item
            ssize_t         remove(const TYPE&);

    //! remove several items
    inline  ssize_t         removeItemsAt(size_t index, size_t count = 1);
    //! remove one item
    inline  ssize_t         removeAt(size_t index)  { return removeItemsAt(index); }

    /*
     * these inlines add some level of compatibility with STL.
     */
    typedef TYPE* iterator;
    typedef TYPE const* const_iterator;

    inline iterator begin() { return editArray(); }
    inline iterator end()   { return editArray() + size(); }
    inline const_iterator begin() const { return array(); }
    inline const_iterator end() const   { return array() + size(); }
    inline void reserve(size_t n) { setCapacity(n); }
    inline bool empty() const{ return isEmpty(); }
    inline iterator erase(iterator pos) {
        ssize_t index = removeItemsAt(pos-array());
        return begin() + index;
    }

protected:
    virtual void    do_construct(void* storage, size_t num) const;
    virtual void    do_destroy(void* storage, size_t num) const;
    virtual void    do_copy(void* dest, const void* from, size_t num) const;
    virtual void    do_splat(void* dest, const void* item, size_t num) const;
    virtual void    do_move_forward(void* dest, const void* from, size_t num) const;
    virtual void    do_move_backward(void* dest, const void* from, size_t num) const;
    virtual int     do_compare(const void* lhs, const void* rhs) const;
};

具体实现

文件路径:system\core\libutils\include\utils\SortedVector.h

实现方面,和 Vector 也是类似的,主要调用父类实现的函数,还有 TypeHelpers.h 中封装的一些底层操作。

需要注意的是 do_compare 的实现,它调用了 TypeHelpers.h 中的 compare_type 函数。

从这里可以看到,用于比较的是 lhsrhs 指针所指向的元素的值,如果 TYPEint,则此处就是直接比较数值大小了。

template<class TYPE>
int SortedVector<TYPE>::do_compare(const void* lhs, const void* rhs) const {
    return compare_type( *reinterpret_cast<const TYPE*>(lhs), *reinterpret_cast<const TYPE*>(rhs) );
}

compare_type 又是基于 strictly_order_type 函数实现的,此处看起来有点绕,但是可以分别假定 lhsrhs 的值,看看其观察其返回值。

最终可以发现:

  • lhs > rhs 时,函数返回值为 1
  • lhs = rhs 时,返回值为 0
  • lhs < rhs 时,返回值为 -1
template<typename TYPE> inline
int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
    return (lhs < rhs) ? 1 : 0;
}

template<typename TYPE> inline
int compare_type(const TYPE& lhs, const TYPE& rhs) {
    return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
}

小结

这两个类中涉及到了 TypeHelpers.h 中封装的一些函数,这些函数都是非常底层的实现,有时间可以仔细看看。
比较需要关注的可能是 SortedVector 中定义的比较函数,它比较的是指针指向的元素的值,这个值取决于 TYPE 这个类型的 operator * 的具体定义。

 类似资料: