2012-02-09 52 views
2

我試圖做一個向量自自學C++,並再次我就死在什麼似乎並不能修復它。 請原諒你即將看到的可怕的代碼混亂。這也是我在這個網站上的第一篇文章,所以這篇文章的格式可能也會關閉,對不起。嘗試使用模板

有兩個文件:main.cpp中和vect1.h (無vect1.cpp因爲它看起來像只在頭文件掛出模板)


main.cpp中:

#include <iostream> 
#include "vect1.H" 

using namespace std; 

int main(){ 
    vect1<int> inst1(10); 
    inst1[9]=4; 
    cout<<inst1[9]<<endl; 
    //----- 
    vect1<double> inst2(10); 
    inst2[5]=5.112; 
    cout<<inst2[5]<<endl; 
    //----- 

    //====PART 2=====// 
    cout<<"--------"<<endl; 
    inst2[9]=999; 
    cout<<inst2[9]<<endl; 
    //inst2.pop(); 
    inst2.push(2); 
    cout<<inst2[9]<<endl; 
    cout<<inst2[10]<<endl;//New block 
system("PAUSE"); 
return 0;} 

vect1.h:

#ifndef VECT1_H 
#define VECT1_H 
#include <iostream> //DEBUG 
template <class T> 
class vect1{ 
private: 
    T *ptr; 
    T total; //work on this 
    int units; 
    int counter; 
public: 
    //vect1(); 
    vect1(T); 
    vect1(); 
    T &operator[](const int &); 
    void pop(); 
    void push(T); 

}; 
//--------------------- 

/* 
template <class T> 
    vect1<T>::vect1(){ 
     ptr = new int [0]; 
    } 
*/ 

template <class T> 
    vect1<T>::vect1(T number){ 
     ptr = new T [number]; 
      total=0; 
      units=(int)number; 
     for(counter=0;counter<number;counter++){ 
      ptr[counter]=0; 
     } 
    } 
    /* now the destruct is giving me errors... 
template <class T> 
    vect1<T>::~vect1(){ 
     total=0; 
     delete[] ptr; 
    }*/ //<<this line tosses a C2039 error 

template <class T> 
    T &vect1<T>::operator[](const int & ref){ 
     if(ref>0 && ref<(units)){ 
      return ptr[ref]; 
     }else{ 
      throw "Error! Out of range!"; //<<make catch 
     } 
    } 
//-------- 
template <class T> 
    void vect1<T>::pop(){ 
     units = (units-1); 
     T *tempPtr; 
     tempPtr = new T[units]; 
      for(counter=0;counter<units;counter++){ 
       tempPtr[counter]=ptr[counter]; 
      } 
     delete[] ptr; 
     ptr = new T[units]; 
      for(counter=0;counter<units;counter++){ 
       ptr[counter]=tempPtr[counter]; 
      } 
     delete[] tempPtr; 
    } 
//-- 
template <class T> 
    void vect1<T>::push(T pushnum){ 
     units++; 
     const int newsize=(int)units; //<<<<< 
     T *tempPtr; 
     tempPtr = new T[units]; 
      for(counter=0;counter<(units-1);counter++){ 
       tempPtr[counter]=ptr[counter]; 
      } 
      //tempPtr[(int)units]=pushnum; 
     delete[] ptr; 
      std::cout<<units<<std::endl;//<<DEBUG 
     ptr = new T[units]; 
      for(counter=0;counter<(units-1);counter++){ 
       ptr[counter]=tempPtr[counter]; 
       //ptr[9]=101; 
      } 
     ptr[newsize]=pushnum; /* <<bleh */ 
     //ptr[newsize]=12321; //DEBUG //<<Even this isn't working... 
     delete[] tempPtr; 
    } 
//--------------------- 
#endif 

輸出(控制檯):

4 
5.112 
-------- 
999 
11 
999 
-6.27744e+066 
Press any key to continue . . . 

我們的計劃是讓所以當你POP(),它會創建T的新的臨時數組複製一切,但最後一個塊從原始數組到原始數組,刪除原始數組,然後創建一個比以前小一個尺寸的新數組,然後將所有數據發回,刪除臨時數組。推(數字)相同的想法,只是相反。 Push會將自身複製到temp中,push會刪除自身,然後將其自身重新創建爲1更大的尺寸,然後將所有內容從temp推送到temp並刪除temp。然後將推送的號碼發送到新塊中。所以這個程序應該在第二個「999」行之後打印出'2'。但相反,我得到「-6.27744e + 066」。

POP()似乎工作。八九不離十。推(num)雖然有真正的問題。我似乎也突然從我的析構函數中得到一個C2039錯誤。之前沒有這樣做,我還沒有改變任何東西。

我真的很感激,如果有人可以查看這個爛攤子,並給我什麼來解決一些提示。謝謝!

我使用Visual Studio 2010爲我的編譯器。

這是我生成日誌(有一些不錯的錯誤/警告去用它!):

1>------ Rebuild All started: Project: chapter 16-5, Configuration: Debug Win32 ------ 
1>Build started 2/9/2012 5:34:01 PM. 
1>_PrepareForClean: 
1> Deleting file "Debug\chapter 16-5.lastbuildstate". 
1>InitializeBuildStatus: 
1> Creating "Debug\chapter 16-5.unsuccessfulbuild" because "AlwaysCreate" was specified. 
1>ClCompile: 
1> main.cpp 
1>e:\programming(cpp)\chapter 16-5\chapter 16-5\vect1.h(31): warning C4244: 'initializing' : conversion from 'double' to 'unsigned int', possible loss of data 
1>   e:\programming(cpp)\chapter 16-5\chapter 16-5\vect1.h(30) : while compiling class template member function 'vect1<T>::vect1(T)' 
1>   with 
1>   [ 
1>    T=double 
1>   ] 
1>   e:\programming(cpp)\chapter 16-5\chapter 16-5\main.cpp(11) : see reference to class template instantiation 'vect1<T>' being compiled 
1>   with 
1>   [ 
1>    T=double 
1>   ] 
1>Manifest: 
1> Deleting file "Debug\chapter 16-5.exe.embed.manifest". 
1>LinkEmbedManifest: 
1> chapter 16-5.vcxproj -> E:\Programming(CPP)\chapter 16-5\Debug\chapter 16-5.exe 
1>FinalizeBuildStatus: 
1> Deleting file "Debug\chapter 16-5.unsuccessfulbuild". 
1> Touching "Debug\chapter 16-5.lastbuildstate". 
1> 
1>Build succeeded. 
1> 
1>Time Elapsed 00:00:10.62 
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ========== 
+3

查看源代碼的'的std :: VECTOR'。實現自定義向量時有很多陷阱(幾乎總是與異常安全有關)。對你更好的可能是學習如何使用* std :: vector。 – 2012-02-09 23:44:28

+0

你的意思是帶有「#包括」的基本載體?我以前使用過它,但從來沒有真正看過它的代碼。不能相信我沒有想到這一點。謝謝! – Natriacid 2012-02-10 00:09:51

回答

1
template <class T> 
vect1<T>::vect1(T number){ 
    ptr = new T [number]; 
    total=0; 
    units=(int)number; 
    for(counter=0; counter<number; counter++) { 
     ptr[counter]=0; 
    } 
} 

此構造爲number對象分配空間,但number有普通型T,你將其轉換爲int。如果你想有一個字符串或對象的矢量,轉換爲int失敗。 number應該有int類型。通常不需要投射,它可能是不良設計的一個症狀(繼承除外 - dynamic_cast)。

因爲T可以是任何東西,你不能在構造函數初始化它,你必須把它留給你的向量的用戶。


T &vect1<T>::operator[](const int & ref){ 

您使用const引用,因爲你很可能告知,這比按值傳遞速度更快。那麼這對於較大的對象是適用的,而不適用於int。參考基本上只是另一個指針(使用不同的語法)。該函數將一個地址傳遞給目標變量。指針和int通常同樣大,所以這裏沒有改進,通過指針訪問肯定比直接訪問該值慢。


template <class T> 
void vect1<T>::pop(){ 
    units = units-1; 
    T *tempPtr = new T[units]; 
    for(counter=0;counter<units;counter++){ 
     tempPtr[counter]=ptr[counter]; 
    } 
    delete[] ptr; 
    ptr = tempPtr; 
} 

沒有必要複製回ptr數據就足以複製指針。


template <class T> 
void vect1<T>::push(T pushnum){ 
    units++;   
    T *tempPtr = new T[units]; 
    for(counter=0;counter<(units-1);counter++){ 
     tempPtr[counter]=ptr[counter]; 
    } 
    tempPtr[units-1]=pushnum; // New item is at units-1 position! 
    delete[] ptr; 
    ptr=tempPtr; // Again, just assign the pointer. 
} 

並添加析構函數釋放分配的內存。

我希望這有助於。我爲我的英語不好對不起。

+0

Bleh。我還有很長的路要走。我忘了我可以把tempptr的地址扔給ptr。有太多的錯誤,它很雜亂,我不如重新開始。時間刪除一切,從頭開始!至少我會記得更好的東西,我輸入他們。謝謝! – Natriacid 2012-02-10 01:07:52

0

眼前的問題,我看到的是:

const int newsize=(int)units; 
ptr = new T[units]; 
...  
ptr[newsize]=pushnum; 

也就是說,你分配newsize對象,但在這裏,你正在訪問一個超出範圍值:只有指數0 ... newsize - 1可用。這也意味着您可能錯過了初始化索引newsize - 1處的值,這可能會導致您引用的值。

這就是說,有幾件事情,而在尋找的代碼,我注意到:

  1. 你並不需要多次分配內存在你push()功能!只需創建一個足夠大的數組,將內容複製並放置到位。在一個可調整大小的矢量的實際實現中,您會過度分配空間,並且只會在該內存耗盡時才分配新內存。重新分配時,您會使用大於1的因子(例如1.5或2)來確保不會頻繁重新分配。
  2. 類分配內存也應該釋放內存在他們的析構函數,即你需要實現析構函數。由於這種類型似乎也是可複製的,但默認生成的拷貝構造和拷貝分配做錯了事情,所以您還需要定義這些。
+0

由於構建日誌中的警告,我絕望了,所以我試圖追蹤源代碼,但沒有運氣。那時候我添加了newsize變量,直到那時我才用「ptr [units] = pushnum」,我忘了撤消它。 是的,我知道。我有很多東西需要學習。我沒有想到這個想法。下次嘗試重新分配更多空間。 我曾嘗試製作一個析構函數,它工作得很好。然後,我想我在某個地方做了一些事情並將其破壞了。如果我現在取消註釋,我會在一個奇怪的地方發現C2039錯誤(最後,沒有代碼,只是'}')。 – Natriacid 2012-02-10 00:04:26