向Vector实现添加函数

时间:2011-03-02 15:14:21

标签: c++ vector

我有这个矢量的实现,我已经使用教科书中的示例进行了几天的研究:

#include <iostream>
#include <string>
#include <cassert>
#include <algorithm>
#include <cstring>



// Vector.h

using namespace std;

template <class T>
class Vector
{
public:

   typedef T * iterator;

   Vector();
   Vector(unsigned int size);
   Vector(unsigned int size, const T & initial);
   Vector(const Vector<T> & v);           // copy constructor
   ~Vector();

   unsigned int capacity() const;         // return capacity of vector (in elements)
   unsigned int size() const;             // return the number of elements in the vector
   bool empty() const;

   iterator begin();                      // return an iterator pointing to the first element
   iterator end();                        // return an iterator pointing to one past the last element
   T & front();                           // return a reference to the first element
   T & back();                            // return a reference to the last element
   void push_back(const T & value);       // add a new element
   void pop_back();                       // remove the last element

   void reserve(unsigned int capacity);   // adjust capacity
   void resize(unsigned int size);        // adjust size
   void erase(unsigned int size);     // deletes an element from the vector

   T & operator[](unsigned int index);    // return reference to numbered element
   Vector<T> & operator=(const Vector<T> &);

private:
   unsigned int my_size;
   unsigned int my_capacity;
   T * buffer;
};

template<class T>//
Vector<T>::Vector()
{
    my_capacity = 0;
    my_size = 0;
    buffer = 0;
}

template<class T>
Vector<T>::Vector(const Vector<T> & v)
{
    my_size = v.my_size;
    my_capacity = v.my_capacity;
    buffer = new T[my_size]; 
    for (int i = 0; i < my_size; i++)
        buffer[i] = v.buffer[i];  
}

template<class T>//
Vector<T>::Vector(unsigned int size)
{
    my_capacity = size;
    my_size = size;
    buffer = new T[size];
}

template<class T>//
Vector<T>::Vector(unsigned int size, const T & initial)
{
    my_size = size; //added = size
    my_capacity = size;
    buffer = new T [size];
    for (int i = 0; i < size; i++)
        buffer[i] = initial;
}

template<class T>//
Vector<T> & Vector<T>::operator = (const Vector<T> & v)
{
    delete[ ] buffer;
    my_size = v.my_size;
    my_capacity = v.my_capacity;
    buffer = new T [my_size];
    for (int i = 0; i < my_size; i++)
        buffer[i] = v.buffer[i];
    return *this;
}

template<class T>//
typename Vector<T>::iterator Vector<T>::begin()
{
    return buffer;
}

template<class T>//
typename Vector<T>::iterator Vector<T>::end()
{
    return buffer + size();
}

template<class T>//
T& Vector<T>::Vector<T>::front()
{
    return buffer[0];
}

template<class T>//
T& Vector<T>::Vector<T>::back()
{
    return buffer[size - 1];
}

template<class T>
void Vector<T>::push_back(const T & v)
{
    if (my_size >= my_capacity)
    reserve(my_capacity +5);
    buffer [my_size++] = v;
}

template<class T>//
void Vector<T>::pop_back()
{
    my_size--;
}

template<class T>//
void Vector<T>::reserve(unsigned int capacity)
{
    if(buffer == 0)
    {
        my_size = 0;
        my_capacity = 0;
    }    
    if (capacity <= my_capacity)
    return;
    T * new_buffer = new T [capacity];
    assert(new_buffer);
    copy (buffer, buffer + my_size, new_buffer);
    my_capacity = capacity;
    delete[] buffer;
    buffer = new_buffer;

}

template<class T>//
unsigned int Vector<T>::size()const
{
    return my_size;
}

template<class T>//
void Vector<T>::resize(unsigned int size)
{
    reserve(size);
    my_size = size;
}

template<class T>//
T& Vector<T>::operator[](unsigned int index)
{
    return buffer[index];
}  

template<class T>//
unsigned int Vector<T>::capacity()const
{
    return my_capacity;
}

template<class T>//
Vector<T>::~Vector()
{
    delete[]buffer;
}

template<class T>
void Vector<T>::erase(unsigned int size)
{

}

int main()
{  

   Vector<int> v;

   v.reserve(2);
   assert(v.capacity() == 2);

   Vector<string> v1(2);
   assert(v1.capacity() == 2);
   assert(v1.size() == 2);
   assert(v1[0] == "");
   assert(v1[1] == "");

   v1[0] = "hi";
   assert(v1[0] == "hi");

   Vector<int> v2(2, 7);
   assert(v2[1] == 7);

   Vector<int> v10(v2);
   assert(v10[1] == 7);

   Vector<string> v3(2, "hello");
   assert(v3.size() == 2);
   assert(v3.capacity() == 2);
   assert(v3[0] == "hello");
   assert(v3[1] == "hello");

   v3.resize(1);
   assert(v3.size() == 1);
   assert(v3[0] == "hello");

   Vector<string> v4 = v3;
   assert(v4.size() == 1);
   assert(v4[0] == v3[0]);
   v3[0] = "test";
   assert(v4[0] != v3[0]);  
   assert(v4[0] == "hello");

   v3.pop_back();
   assert(v3.size() == 0);

   Vector<int> v5(7, 9);
   Vector<int>::iterator it = v5.begin();
   while (it != v5.end())
   {
      assert(*it == 9);
      ++it;
   }

   Vector<int> v6;
   v6.push_back(100);
   assert(v6.size() == 1);
   assert(v6[0] == 100);
   v6.push_back(101);
   assert(v6.size() == 2);
   assert(v6[0] == 100);
   v6.push_back(101);

   cout << "SUCCESS\n";
}

到目前为止它工作得很好,但我想添加一些我找不到示例的函数,一个SWAP函数,它会查看向量的两个元素并切换它们的值和一个ERASE将删除向量中的特定值或值范围的函数。我应该如何开始实现这两个额外的功能?

4 个答案:

答案 0 :(得分:1)

我会用这个练习来看看迭代器设计模式是如何工作的。

vector没有交换,因为此操作可以使用迭代器以更通用的方式完成。 std :: swap算法为你做了这个, 见here

同样对于擦除,你可能想要使用std :: transform算法 - http://www.cplusplus.com/reference/algorithm/transform/ - 完全取决于擦除的含义(你的意思是删除或覆盖?)

答案 1 :(得分:0)

实施交换应该非常容易。复制缓冲区[A],将缓冲区[B]分配给缓冲区[A],将复制分配给缓冲区[B]。

擦除也应该是相当直接的。给定要擦除的元素范围,将范围之后的元素向左移动范围的大小,然后调整向量的大小。

答案 2 :(得分:0)

您不需要定义自己的交换函数,因为<iostream>标头包含函数std::swap。但是,如果您不想使用std::swap,您可以像这样定义自己的交换函数:

template<typename _Tp>
void swap(_Tp &a, _Tp &b)
{
    _Tp tempVal = a;
    a = b;
    b = tempVal;
}

现在关于擦除功能:因为你正在用数组实现向量,你的擦除功能应该是:

1)调用要删除的元素的析构函数(如果有)

2)将删除元素右侧的所有元素移动到左侧

3)返回一个随机访问迭代器,指向函数调用擦除的最后一个元素后面元素的新位置,如果操作擦除了序列中的最后一个元素,则为向量结束。

4)调整矢量大小

假设你有删除一个元素的擦除函数,那么删除迭代器a,b所有元素的擦除版本将是这样的:

iterator
erase(iterator first, iterator last)
{
while (first != last)
    first = erase(first);
return last;
}

答案 3 :(得分:-1)

交换两个元素很简单,因为std :: swap会为你做这件事。

擦除意味着您必须复制擦除后的元素以填充“孔”。然后减去大小。

顺便说一下,你有一个问题,你从另一个向量复制和分配。您复制其他向量的容量,但在缓冲区中分配大小元素。这会回来再次咬你! : - )