2014-10-05 3 views
-4

Я изучаю cpp самостоятельно (надеюсь, я уже не отпугнул вас), я понимаю, что такое указатель или ссылка, и я думаю, что получаю ссылку на указатель является.Удаление ссылки на указатель вызывает ошибку

Я написал код, который происходит сбой в delete[] ranking;:

open(file) это простая функция, чтобы открыть текстовый файл, который содержит строку и 3 целых чисел в каждой строке, которая входит в структуру zuzel:

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; 
} 

я узнал, что вы не должны удалить то, что вы не сделали новый, но, например, что код не откажет:

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' Тогда я могу посоветовать вам научиться использовать' std :: vector' вместо написания низкоуровневого C для имитации динамического массива. – PaulMcKenzie

ответ

2

Это будет достаточно, чтобы написать

zuzel * rank = 0; 

Что касается второго фрагмента кода, то он имеет неопределенное поведение.

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 

Поскольку rank не инициализирован, он указывает на неизвестной части памяти, и ваш код просто tryes к delete[] части, в любом случае ...

Вам нужно сделать установить указатель для решения 0 по используя один из них:

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 это абсолютно самый забавный и продуктивный язык на планете (IMHO). –

Смежные вопросы