繁体   English   中英

在C ++中的Vector实现中遇到两个函数的麻烦

[英]Having Trouble With Two Functions In An Implementation of Vector in C++

我写了一个vector的实现,根据给出的test main()程序可以编译但不能正常工作。

我确定错误出在我的push_back()函数或reserve()函数中,但我不确定到底是什么错误。

有人可以浏览一下这两个功能,然后告诉我是否缺少某些东西或需要更改吗?

#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//Done
   ~Vector();

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

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

   void reserve(unsigned int capacity);   // adjust capacity //Done
   void resize(unsigned int size);        // adjust size //Done

   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;
    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;
}

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";
}

我认为您的问题出在以下代码中:

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

注意第一行

my_size;

没有效果。 我想你打算写

my_size = size;

当我在计算机上执行此操作后,它解决了问题,所有测试均通过。 Valgrind确认没有泄漏或内存损坏。

但是,您可能还需要研究此代码的其他部分。 这是要检查的事项的快速清单:

  1. 在用于reserve的代码中,您可以通过写T* new_buffer = new T[capacity]分配缓冲区,然后使用assert来确认该缓冲区为非NULL 在C ++中,当您使用newnew[]分配内存时,您将永远不会返回NULL指针。 相反,如果分配失败,程序将引发bad_alloc异常。 您可以显式地要求您以永远不会引发异常的方式获取内存,但这可能不是您想要在此处执行的操作。

  2. 您有一个不带标记的构造函数Vector(unsigned int size) ,没有标记为explicit 这意味着C ++会将其视为隐式转换构造函数,并允许您编写类似Vector<int> v = 137; ,因为编译器会将其解释为Vector<int> v(137) 这可能不是您想要的,所以我建议explicit标记构造explicit以禁止此行为。

  3. 确保Vector存在足够空间的代码是有效的,但是您的增长策略效率不高。 特别是,如果您一次使向量保持五个元素的增长,那么执行n push_back s所需的时间将是O(n 2 ),这不是很好。 较常见的策略是在需要空间时将向量的大小加倍。 使用摊销分析 ,您可以证明这意味着n次插入仅花费O(n)时间,这比您当前的方法要好得多。

  4. 您的赋值运算符( operator = )包含一个错误,如果您通过编写类似v = v的向量来为其自身分配矢量,则会导致不确定的行为。 这样做的原因是您的赋值运算符delete[]的缓冲区,然后尝试从另一个对象复制。 但是,如果另一个对象与您自己的对象完全相同,则您将尝试从刚删除的指针中读出。 要解决此问题,您可能需要在operator=加上一个if (this != &v) 这意味着,如果您尝试将Vector分配给它自己,它将无操作,而不会在运行时失败。

希望这可以帮助!

乍一看,这行my_size; Vector<T>::Vector(unsigned int size, const T & initial)我觉得很奇怪。 您可能说的是my_size = size;

我没有尝试调试您的代码以进行验证,但乍看之下push_backreserve看起来很适合您的用途(我假设您不在乎异常安全性或在适当/预期的时间破坏删除的对象)。

但是,我在以下实现中看到一些明显的逻辑问题:

  • template<class T> Vector<T>::Vector(const Vector<T> & v)template<class T> Vector<T> & Vector<T>::operator = (const Vector<T> & v) :复制/分配默认构造的空Vector时会发生什么?
  • template<class T> Vector<T>::Vector(unsigned int size) :当size == 0时会发生什么?
  • template<class T> Vector<T>::Vector(unsigned int size, const T & initial) :与上面相同,和my_size; 作为一个独立的陈述似乎很错误
  • resizeresize应缩小Vector (减少其容量), reserve

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM