2011-03-02 35 views
0

我寫了向量的實現,編譯,但不是按照我給出的測試main()程序正常工作。遇到問題,兩個函數向量C++中的實現

我確定這個錯誤出現在我的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"; 
} 
+0

哪個斷言失敗? – user470379 2011-03-02 01:24:09

+0

@ user470379 - 現在工作正常,謝謝你的幫助。 – UndefinedReference 2011-03-02 01:25:08

回答

1

乍一看,這條線在my_size;罷工Vector<T>::Vector(unsigned int size, const T & initial)我,很奇怪。你可能意味着它是my_size = size;

+0

@ Eugen Constantin Dinca - 哇,我不能相信它,但實際上確定了整個程序。我覺得沒有抓住它是可笑的。非常感謝你! – UndefinedReference 2011-03-02 01:23:55

+0

您應該只設置尺寸您確認後的分配工作,否則你會把矢量處於不一致的狀態。訣竅是做任何事情,可以使用臨時變量拋出異常,然後在確認它已經工作並且不再導致問題時交換/分配內部。 – David 2011-03-02 01:30:51

3

我覺得你的問題是在此代碼:

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禁止這種行爲。

  3. Vector存在於您確保足夠空間的代碼是有效的,但你的發展戰略是不是很有效。特別是,如果你一直在一個時間增長向量五行,則所需的時間做ňpush_back旨意爲O(N ),這是不是很不錯的。更常見的策略是在需要空間時將矢量的大小加倍。使用amortized analysis,可以表明這意味着n次插入只需要O(n)次,這比現在的方法要好得多。

  4. 您的賦值運算符(operator =)包含一個錯誤,如果您通過編寫類似於v = v的東西將向量分配給自己,則會導致未定義的行爲。原因是您的賦值運算符delete[]是緩衝區,然後嘗試從其他對象複製。但是,如果其他對象與您自己的對象完全相同,那麼您將嘗試讀出剛刪除的指針。爲了解決這個問題,你可能想包圍operator=你的代碼檢查if (this != &v)。這意味着如果您嘗試將Vector分配給自己,它將不會在運行時發生故障而無法運行。

希望這有助於!

0

我還沒有嘗試過調試代碼驗證,而且一目瞭然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):時會發生什麼大小== 0?
  • template<class T> Vector<T>::Vector(unsigned int size, const T & initial):同上,並my_size;作爲一個獨立的聲明似乎完全錯誤
  • resizeresize應該收縮Vector(減少它的容量),reserve