2012-02-09 51 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