массивы, removeFirst () не работает?

0

Я создал метод, который должен удалить первый элемент массива, однако, когда я запускаю свой код, отладчик переворачивается, и я не уверен, почему.

Это мой метод removeFirst():

Loan & ListOfLoans ::  removeFirst(){
    index = 0;
    //determine if the container needs to be shrunk
    if((numberOfElements < capacity/4) && (capacity >= 4)){ // shrink container when     array is 1/4 full
        cout<<"shrinking array! \n";
        Loan ** temp = elements;
        elements = new Loan * [numberOfElements/2];
        //copy temp array to elements
        for(int i = 0; i<numberOfElements; i++){
            temp[i] = elements[i];
            numberOfElements = numberOfElements/2;
            delete [] temp;
        }
    }
    numberOfElements--;
    return **elements;
} 

И мой заголовочный файл для хорошей оценки:

#include <iostream>
#include "loan.h"

using namespace std;

class ListOfLoans {

public:
ListOfLoans(int initial_size=4);

~ListOfLoans(void);


 void add(Loan & aLoan);
 Loan & first() ;
 Loan & removeFirst();
   // answer the first element from the list and remove it from the list
    // if the resulting list is more than three quarters empty release some memory
 Loan & removeLast(); 
   // answer the last element from the list and remove it from the list
    // if the resulting list is more than three quarters empty release some memory
 Loan & next();
 int size(); 

private: 
Loan ** elements; //actuall stuff in the array m_pnData;
int numberOfElements; //number of elements in the list  stize of the array? m_nLength
int capacity; //size of the available array memory 
int index; //used to help with the iteration
};
Теги:
arrays

2 ответа

0
Лучший ответ

В этом коде есть много проблем. Вот аннотированная копия.

// Return by reference cannot be used if you are removing the element.
// This looks like a Java-ism.
Loan & ListOfLoans ::  removeFirst(){
    // unused variable
    index = 0;

    if((numberOfElements < capacity/4) && (capacity >= 4)){
        cout<<"shrinking array! \n";
        Loan ** temp = elements;
        // you are allocating an array of size numberOfElements/2...
        elements = new Loan * [numberOfElements/2];

        // then accessing elements which are way past its end.
        for(int i = 0; i<numberOfElements; i++){
            temp[i] = elements[i];
            // you are halving the array size in every iteration
            numberOfElements = numberOfElements/2;
            // you are deleting temp in every iteration,
            // causing double-frees
            delete [] temp;
        }
    }
    // if the array does not need to be shrunk,
    // you are actually removing the last element.
    // the removed element is not freed and is leaking.
    numberOfElements--;
    // you are returning the first element,
    // which is not removed.
    return **elements;
}

Я настоятельно рекомендую заменить ListOfLoans контейнером STL, таким как std::deque. Если вы не можете этого сделать, это минимальная фиксированная версия.

Loan ListOfLoans::removeFirst() {
    Loan to_return;
    if (numberOfElements == 0) {
        return to_return; // return default value, there is nothing to remove
    }
    if ((numberOfElements < capacity/4) && (capacity >= 4)) {
        Loan **old = elements;
        capacity = capacity / 2;
        elements = new Loan*[capacity];
        for (int i=0; i < numberOfElements - 1; ++i) {
            elements[i] = old[i+1];
        }
        to_return = *old[0];
        delete old[0];
        delete[] old;
    } else {
        to_return = *elements[0];
        delete elements[0];
        for (int i=0; i < numberOfElements - 1; ++i) {
            elements[i] = elements[i+1];
        }
    }
    --numberOfElements;
    return to_return;
}
  • 0
    Я действительно новичок в c ++, поэтому, пожалуйста, будьте терпеливы со мной ... Я не могу использовать объявление Loan to_return, потому что нет подходящего конструктора по умолчанию ... Я думаю, что мой конструктор требует, чтобы я инициировал каждый новый заем с 5 параметрами , и я не могу иметь два конструктора, так как мне дали файл заголовка и я не могу его изменить
  • 0
    В этом случае исследуйте boost::ptr_deque или boost::ptr_list . Это обертки для стандартных контейнеров, которые позволяют им работать с указателями.
1

Попробуйте переместить delete [] temp; под циклом for.

Похоже, что одна проблема может заключаться в том, что delete [] temp; неоднократно вызывается в цикле for. Первая итерация через цикл, память, связанная с temp будет освобождена. Последующие итерации через цикл получат доступ к освобожденной памяти.

Могут быть и другие проблемы. Было бы очень полезно увидеть выходные данные отладчика.

  • 0
    Хороший звонок на удаление. К сожалению, это не проблема. Я не совсем понимаю, что происходит с отладчиком (я никогда не использовал его), но я запускаю код в Microsoft Visual Studio, и файл iosfwd продолжает появляться.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню