2012-02-09 2 views
2

저는 스스로 C + +를 스스로 가르치려고합니다. 그리고 다시 한 번 뭔가 붙어있어 고칠 수없는 것 같습니다. 당신이 보려고하는 코드의 끔찍한 혼란을 용서하십시오. 이것은 또한이 사이트의 첫 번째 게시물이기 때문에 게시물의 형식도 아마 미안합니다.템플릿을 사용하여 벡터를 만들려고 시도합니다.

두 개의 파일이 있습니다 MAIN.CPP 및 vect1.h (NO 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 
,369 (콘솔에서)

출력 :

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

계획은 당신이) (팝업 때 그래서 T의 새로운 임시 배열을 생성하고 마지막 블록을 제외한 모든 것을 복사 할 수 있도록하는 것입니다 원래 배열에서 임시 배열로, 원래 배열을 삭제 한 다음 이전 배열보다 작은 한 배열을 새로 만들고 모든 배열을 삭제하여 임시 배열을 삭제하십시오. 푸시 (숫자)에 대한 동일한 생각, 반대 방향 만. 푸시는 자체를 임시로 복사하고, 푸시는 자체를 삭제 한 다음 크기가 1 크기로 다시 생성 한 다음 임시의 모든 것을 푸시하고 임시 삭제합니다. 그런 다음 밀어 넣기로 전송 된 번호를 새 블록으로 보냅니다. 따라서이 프로그램은 두 번째 "999"라인 다음에 '2'를 출력해야합니다. 하지만 대신 "-6.27744e + 066"이 나옵니다.

Pop()이 작동하는 것 같습니다. 정렬. 하지만 푸시 (num)와 함께 진짜 문제가 있습니다. 나는 또한 갑자기 내 소멸자로부터 C2039 오류를 얻는 것 같다. 그것은 이전에 그렇게하지 않았고, 아직 그것에 어떤 변화도 일으키지 않았습니다.

누군가가이 난장판을 살펴보고 해결해야 할 부분에 대한 조언을 주시면 감사하겠습니다. 감사!

제 컴파일러로 Visual Studio 2010을 사용합니다.

내 빌드 로그 (일부 좋은 오류/경고와 함께 그것으로 이동합니다!)되어있다

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

, 당신은 할당 : 내가 발견

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를 * 사용하는 법을 배우는 것입니다. –

+0

기본 벡터가 "#include "과 함께 오는 것을 의미합니까? 이전에이 코드를 사용했지만 실제로 코드를 살펴 보지 않았습니다. 내가 그렇게 생각하지 않았다는 것을 믿을 수 없다. 감사! – Natriacid

답변

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 개체에 대한 공간을 할당하지만 일반적인 유형 Tnumber 가지고 있으며, 당신은 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

0

즉각적인 문제는 이것이다 newsize 개체가 있지만 여기에 범위를 벗어나는 값에 액세스하고 있습니다. 0 ... newsize - 1 인덱스 만 사용할 수 있습니다. 이는 또한 색인 newsize - 1의 값을 초기화하지 않았을 때 사용자가 인용 한 값으로 이어질 수 있음을 의미합니다.

  1. 당신은 당신의 메모리를 push() 기능을 여러 번 할당 할 필요가 없습니다 말했다

    는 코드를 보면서 내가 발견 몇 가지가 있습니다! 충분히 큰 배열을 만들고 내용을 복사 한 다음 제자리에 넣으십시오. 크기를 조정할 수있는 벡터를 실제로 구현할 때 공간을 너무 많이 할당하고이 메모리가 고갈 될 때만 새 메모리를 할당합니다.재 할당 할 때 자주 재 할당하지 않도록 1보다 큰 계수 (예 : 1.5 또는 2)를 사용하십시오.

  2. 메모리를 할당하는 클래스는 소멸자의 메모리도 해제해야합니다. 즉 소멸자를 구현해야합니다. 이 유형은 복사 가능하지만 기본 생성 된 사본 구성 및 사본 할당이 잘못된 것을 수행하므로이를 정의해야합니다.
+0

빌드 로그에있는 경고 때문에 절망적 이었기 때문에 운이 좋지 않은 소스를 추적하려고했습니다. 그 때까지 newsize 변수를 추가했습니다. 그 때까지는 "ptr [units] = pushnum"을 사용했습니다. 그냥 실행 취소하는 것을 잊었습니다. 그래, 알아. 나는 배울 것이 많다. 나는 그 생각을 생각하지 않았다. 다음에 재 할당 할 때마다 더 많은 공간을 추가하려고 노력할 것입니다. 소멸자를 만들려고했는데 잠시 동안 잘 작동했습니다. 그럼 내가 뭔가 어딘가에 줄을 부순 것 같아. 내가 지금 그것을 주석 처리하지 않으면 별난 지점에서 C2039 오류를 얻을 것이다. (끝에 코드가없고 단지 '}'). – Natriacid

관련 문제