2014-10-05 9 views
-4

나 혼자서 cpp를 배우고있다. (나는 이미 너를 놀라게하지 않았기를 바란다.) 나는 포인터 나 참조가 무엇인지 이해하고 있으며 포인터에 대한 참조를 얻는다 고 생각한다. 입니다.포인터 참조를 삭제하면 프로그램이 충돌 함

void read_file(std::ifstream & file, zuzel *& ranking) 
{ 
    if(!open(file)) 
    return; //exit function if reading a file failed 

    int size = 1; 

    while(!file.eof()) 
    { 
     zuzel * update = new zuzel[size]; 

     if(ranking != NULL) memcpy(update, ranking, (size-1)*sizeof(*ranking)); //copy existing contents 

     file >> update[size - 1].nazwa >> update[size - 1].zawodnicy >> update[size - 1].mecze >> update[size - 1].punkty;// add a new team 

     delete[] ranking; //delete old data 
     std::cout << "tst"; //just to see if it crashes 
     ranking = update; 

     size++; 
    } 
} 

int main() 
{ 
    zuzel * rank; 
    std::ifstream file; 
    read_file(file, rank); 
    return 0; 
} 
:

open(file)

그냥 zuzel 구조로가는 문자열과 3 개 정수 각 라인이 포함 된 TXT 파일을 열 수있는 간단한 기능입니다 : 내가 delete[] ranking;에서 충돌 코드를 작성했습니다

나는 당신이 새하지 않았다 무언가를 삭제하지 않도록 발견하지만, 예를 들어 그 코드는 충돌하지 않습니다

void funk(int *& a) 
{ 
    delete[] a; 
} 

int main() 
{ 
    int a[3] = {3, 4, 6}; 
    int * p = a; 
    funk(p); 
    return 0; 
} 

어떻게 그 충돌을 해결할 수 있습니까? 나는 그것이 왜 그렇게 행동하는지 몇 가지 간단한 설명을 많이해야 할 것입니다.

+3

"크래시가 발생하지 않음"이 코드가 유효 함을 의미하지 않습니다. – Mat

+1

'나는 당신이 새로운 것을 만들지 말아야한다는 것을 알았지 만, 예를 들어 그 코드는 크래쉬가 안된다. '이런 나쁜 C++ 코드가 충돌한다는 보장은 없다. – PaulMcKenzie

+1

'나는 혼자서 cpp를 배우고있다. '그런 다음 동적 배열을 시뮬레이트하기 위해 하위 수준 C를 작성하는 대신'std :: vector'를 사용하는 방법을 배우도록 제안 할 수 있습니다. – PaulMcKenzie

답변

2

이 두 번째 코드 다음은 정의되지 않은 한 행동으로

zuzel * rank = 0; 

쓰기에 충분합니다. rank가 초기화되지

1
zuzel * rank; 
//somewhere in read_file: 
delete[] ranking; //ranking is a reference to pointer; 
       //in your case it's referernce to uninitialized pointer rank 

때문에 메모리의 알 수없는 부분에 포인트 및 코드는 단순히

당신은에 의해 0를 해결하기 위해 포인터를 설정 할 필요가 ... delete[] 어쨌든 부분에 tryes 이들 중 하나를 사용하여 :

zuzel * rank=nullptr; //in C++11 
zuzel * rank=NULL; //before C++11 
zuzel * rank=0; //also legal, but I not recommend this 

0 것은 아무것도를 가리키는 것을 의미, 어떤 포인터에 대한 특별한 값입니다.

0에서 delete[] 또는 delete으로 설정된 포인터를 전달할 때 단순히 아무 것도하지 않습니다.

1

배우는 중이므로. 이 방법을 선호하는 방법에 동의하십시오. 이 예외 안전 및 포인터를 사용 방지 (따라서 메모리 관리의 필요성을 피할 수) 당신이 찾을 수

MAIN.CPP :

#include <iostream> 
#include <vector> 
#include <fstream> 
#include <string> 
#include <algorithm> 
#include <iterator> 

struct zuzel 
{ 
    std::string nazwa, zawodnicy, mecze, punky; 
}; 

std::ostream& operator<<(std::ostream& os, const zuzel& z) 
{ 
    return os << z.nazwa << ", " 
    << z.zawodnicy << ", " 
    << z.mecze << ", " 
    << z.punky; 
} 

std::vector<zuzel> read_zuzels(std::string filename) 
{ 
    std::vector<zuzel> results; 

    std::ifstream f(filename.c_str()); 
    f.exceptions(std::ios::badbit); 

    while(!f.eof()) 
    { 
     // add a new team 
     zuzel new_zuzel; 
     f >> new_zuzel.nazwa 
     >> new_zuzel.zawodnicy 
     >> new_zuzel.mecze 
     >> new_zuzel.punky; 

     results.push_back(new_zuzel); 
    } 
    return results; 
} 

using namespace std; 


int main() 
{ 
    vector<zuzel> zuzels = read_zuzels("input.txt"); 
    copy(zuzels.begin(), zuzels.end(), ostream_iterator<zuzel>(cout, "\n")); 
    return 0; 
} 

input.txt를 :

foo1 bar1 baz1 bazzer1 
foo2 bar2 baz2 bazzer2 

출력 :

Compiling the source code.... 
$g++ main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1 

Executing the program.... 
$demo 
foo1, bar1, baz1, bazzer1 
foo2, bar2, baz2, bazzer2 
+1

덕분에, 벡터에 대해 읽어야 할 것입니다. – krzym1

+0

C++을 배울 때 할 수있는 가장 좋은 방법은 표준 라이브러리를 읽는 것입니다. 다음은 시작할 수있는 좋은 곳입니다. http://en.cppreference.com/w/ C++ 여행의 즐거움 - C++ 11 이후로 지구상에서 가장 재미 있고 생산적인 언어입니다. –