Как управлять массивом указателей на объекты? - PullRequest
0 голосов
/ 06 декабря 2011

У меня проблема с массивом указателей на объекты: (..

Мне нужно создать динамический вектор объекта и затем вернуть его в Для того, чтобы манипулировать им в другом классе. В приведенном ниже коде есть Класс события, который является абстрактным, и CarArrival, который наследует от него, и может быть создан.

Внутри класса, который генерирует и заполняет массив, у меня есть эта функция:

Event** EventGenerator::getEvents() {

Event* cars[EVENTS];

for (int i=0; i<EVENTS; i++) {
    cars[i] = new CarArrival(generator->getNextNumber(8,(float)sqrt(0.4)));
}

sort(cars, cars+(EVENTS), Event::cmp);

return cars;

}

Я вызываю эту функцию в другом классе следующим образом:


Event** cars = generator->getEvents();

for(int i=0; i<EVENTS; i++) {
    cout << i <<":" << (*cars)[i]->getScheduleTime() << endl;
}

после печати первого элемента я получаю «Ошибка сегментации».

Я прочитал некоторые вещи в Интернете, и я понимаю, что ошибаюсь, поскольку (* cars) оценивается как указатель на первый элемент массива, фактически я могу напечатать первый элемент, а не другой, но я не могу понять, как получить доступ к каждому элементу массива во втором классе.

Как я могу с этим столкнуться?

Спасибо всем,

Альберто

Ответы [ 4 ]

5 голосов
/ 06 декабря 2011

Я бы посоветовал использовать вместо него std::vector<Event*>. Вы сэкономите много боли таким образом. Он отвечает за все неприятное управление памятью в фоновом режиме, и вы можете легко вставить в него любое количество элементов. Самое приятное в вашем случае, что вы можете просто return a vector, что небезопасно с обычным массивом.

Также ваш Event* cars[EVENTS]; объявлен локально в вашей функции. После того, как вы закончили его, он перестает существовать, что может вызвать ваш Segfault. Вам нужно было бы динамически распределить массив с помощью new, но все же попробуйте его с std::vector, см. Документацию здесь .

РЕДАКТИРОВАТЬ: Пример использования:

std::vector<Event*> EventGenerator::getEvents() {
    std::vector<Event*> cars;
    for (int i=0; i<EVENTS; i++) {
        cars.push_back(new CarArrival(generator->getNextNumber(8,(float)sqrt(0.4))));
    }

    sort(cars.begin(), cars.end(), Event::cmp);

    return cars;
}

std::vector<Event*> cars = generator->getEvents();

for(int i=0; i<cars.size(); i++) {
    cout << i <<":" << (*cars)[i]->getScheduleTime() << endl;
}
3 голосов
/ 06 декабря 2011

Я считаю, что самый простой способ обработки динамического вектора указателей на динамически размещаемые объекты - это использовать boost::ptr_vector.Он обрабатывает все, что вам нужно, включая выделение места для хранения указателей и последующее удаление этих указателей.

2 голосов
/ 06 декабря 2011

Как упомянул Constantinuis, вы возвращаете значение указателя на ячейку памяти, которая действительна только в области действия функции getEvents () (она расположена в стеке).Ты обязательно получишь сегфо в следующий раз.

Возможно, вы захотите выделить память для этого массива в куче (используя 'new', если мой C ++ не слишком ржавый), и тогда вам придется иметь дело с освобождением памяти позже.

http://www.linuxtopia.org/online_books/programming_books/thinking_in_c++/Chapter13.html

2 голосов
/ 06 декабря 2011

Не лучше ли вернуть vector<Event*> или vector<shared_ptr<Event>> вместо необработанных указателей?Таким образом вы получите:

  1. Автоматизация управления памятью
  2. Динамический массив со встроенной длиной вместо фиксированной
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...