首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >矢量实现-简单替换

矢量实现-简单替换
EN

Code Review用户
提问于 2013-01-07 19:56:03
回答 1查看 2.3K关注 0票数 4

这是为了更简单的替代std::vector,为娱乐而写的。它应该和std::vector一样快或者更快,但是不需要有那么多的特性。

它也应该简单易用。

我希望就以下各点作出检讨:

  • 错误
  • 性能
  • 类/函数/变量命名
  • 要添加的有用特性
  • 码结构
  • 还要别的吗

以下是头文件Vector.hpp

代码语言:javascript
复制
#pragma once
#include "../Types.hpp"
#include "../System/Memory/Memory.hpp"

namespace Core
{
    namespace DataStruct
    {
        template<class ItemType> class Vector
        {
            ItemType* VecPtr;
            UInt Capacity;
            UInt Length;

            void AllocSpace();
            void DestroyAll();

            public:
            typedef ItemType* Iterator;
            typedef ItemType const * ConstIterator;

            Vector();
            ~Vector();

            void Reserve(UInt Capacity);

            void Add(ItemType const & Value);
            void Insert(UInt Position, ItemType const & Value);
            void Remove(UInt Position);

            void Clear();
            void Free();

            UInt GetCapacity() const;
            UInt GetLength() const;

            ItemType operator[](UInt Position) const;

            Iterator Begin();
            Iterator End();
            ConstIterator Begin() const;
            ConstIterator End() const;
            ConstIterator CBegin() const;
            ConstIterator CEnd() const;
        };

        #include "Vector.cpp"
    }
}

以及实现Vector.cpp,它被排除在构建之外,并包含在Vector.hpp中,因为它是一个模板。

代码语言:javascript
复制
template <class ItemType> void Vector<ItemType>::AllocSpace()
{
    if(Capacity == 0U)
        Reserve(2U);
    else if(Capacity == Length)
        Reserve(Capacity << 1U);
}

template <class ItemType> void Vector<ItemType>::DestroyAll()
{
    Iterator it = Begin();
    Iterator end = End();
    while(it < end)
        it++->~ItemType();
}

template<class ItemType> Vector<ItemType>::Vector() : VecPtr(NULL), Capacity(0U), Length(0U) {}

template<class ItemType> Vector<ItemType>::~Vector()
{
    Free();
}

template<class ItemType> void Vector<ItemType>::Reserve(UInt Capacity)
{
    ItemType* ptr;

    if(Capacity > this->Capacity)
    {
        ptr = (ItemType*)System::Memory::Alloc(sizeof(ItemType) * Capacity);
        if(VecPtr)
        {
            System::Memory::Copy(VecPtr, ptr, sizeof(ItemType) * this->Capacity);
            System::Memory::Free(VecPtr);
        }
        VecPtr = ptr;
        this->Capacity = Capacity;
    }
}

template<class ItemType> void Vector<ItemType>::Add(ItemType const & Value)
{
    Insert(Length, Value);
}

template<class ItemType> void Vector<ItemType>::Insert(UInt Position, ItemType const & Value)
{
    ItemType* ptr;
    Bool insert;

    AllocSpace();

    //If Position is beyond the end then insert at end.
    insert = Position < Length;
    ptr = insert ? VecPtr + Position : VecPtr + Length;

    if(insert)
        System::Memory::Move(ptr, ptr + 1, sizeof(ItemType) * (Length - Position));

    new((VoidPtr)ptr) ItemType(Value);
    ++Length;
}

template<class ItemType> void Vector<ItemType>::Remove(UInt Position)
{
    ItemType* ptr;

    if(Position < Length)
    {
        --Length;
        ptr = VecPtr + Position;
        ptr->~ItemType();
        if(Position < Length)
            System::Memory::Move(ptr + 1, ptr, sizeof(ItemType) * (Length - Position));
    }
}

template<class ItemType> void Vector<ItemType>::Clear()
{
    DestroyAll();
    Length = 0U;
}

template<class ItemType> void Vector<ItemType>::Free()
{
    if(VecPtr)
    {
        DestroyAll();
        System::Memory::Free(VecPtr);
        VecPtr = NULL;
        Capacity = 0U;
        Length = 0U;
    }
}

template<class ItemType> UInt Vector<ItemType>::GetCapacity() const
{
    return Capacity;
}

template<class ItemType> UInt Vector<ItemType>::GetLength() const
{
    return Length;
}

template<class ItemType> ItemType Vector<ItemType>::operator[](UInt Position) const
{
    return *(VecPtr + Position);
}

template<class ItemType> typename Vector<ItemType>::Iterator Vector<ItemType>::Begin()
{
    return VecPtr;
}

template<class ItemType> typename Vector<ItemType>::Iterator Vector<ItemType>::End()
{
    return VecPtr + Length;
}

template<class ItemType> typename Vector<ItemType>::ConstIterator Vector<ItemType>::Begin() const
{
    return VecPtr;
}

template<class ItemType> typename Vector<ItemType>::ConstIterator Vector<ItemType>::End() const
{
    return VecPtr + Length;
}

template<class ItemType> typename Vector<ItemType>::ConstIterator Vector<ItemType>::CBegin() const
{
    return VecPtr;
}

template<class ItemType> typename Vector<ItemType>::ConstIterator Vector<ItemType>::CEnd() const
{
    return VecPtr + Length;
}

Memory命名空间中的函数调用以下内容:

  • Memory::Alloc -> malloc
  • Memory::Copy -> memcpy
  • Memory::Move -> memmove
  • Memory::Free -> free
EN

回答 1

Code Review用户

发布于 2013-01-07 20:42:42

Vector的第一个也是最明显的缺点是它不满足序列的标准需求。这意味着您的Vector不能与任何标准算法一起使用,也不能与设计用于处理序列的第三方算法一起使用。它只用于存储元素,而不是其他任何东西。

在每次使用Vector时,缺少适当的构造函数/析构函数和赋值操作符都会导致崩溃和泄漏。在这个主题上有很多话要说,请搜索一个基本的C++规则,称为“三的规则”,它将让您知道应该如何编写这些特殊的成员函数来实现正确的语义。

实现的下一个明显缺点是只能获得存储在Vector中的元素的副本。这不仅不方便,它还真的低效。必须复制元素的副本才能读取元素;要写入元素,必须复制、修改所述副本、从Vector中删除元素,然后插入修改后的副本。如前所述,这既不方便,也很低效。对于下标操作符来说,这将是一个更好的方法:

代码语言:javascript
复制
ItemType& operator[](UInt Position){ ... };
ItemType const& operator[](UInt Position) const{ ... };

这将返回对存储元素的引用,因此,如果我们有一个非const Vector,就可以对其进行适当的修改。

另一个重要的缺点是,实现的Vector只适用于标准布局类型。简单地为任何其他类型移动或复制底层内存可能会导致内部值混淆、不变量中断、甚至崩溃和未定义的行为。

命名约定对C++来说是很奇怪的,它似乎是从一种不同的语言,也许是C#带来的。但是语义是不一样的,因此对于一个Vector编码器来说,这个C++看起来很奇怪,而对于一个倾向于认为语义来自C#的C#编码器来说,它似乎是很熟悉的。

您说过,这是为了更简单地替代std::vector。但是,如果我用std::vector替换Vector,代码甚至不会编译,即使会编译,观察到的行为也会有很大的不同。通常情况下,当您使用C++编写代码时,您应该遵守C++约定。这同样适用于任何其他语言。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/20243

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档