C++:Перебор вектора векторов
Вопрос
Привет всем!Я занимаюсь этим проектом, и прямо сейчас я пытаюсь:
- создайте некоторые объекты и сохраните их в векторах, которые будут сохранены в другом векторе V
- выполните итерацию по векторам внутри V
- перебор объектов внутри отдельных векторов
В любом случае, я просто искал в Интернете и наткнулся на функцию stl for_each .Это кажется довольно аккуратным, но у меня с этим проблемы.Я пытаюсь использовать это таким образом:
for_each(V.begin(), V.end(), iterateThroughSmallVectors);
прохождение итерации....просто делает то же самое с переданным ему вектором..
Теперь я получаю странную ошибку времени выполнения "Несовместимые векторные итераторы".Я просмотрел его и не могу найти никакой полезной информации по этому поводу..
Я не знаю, помогает ли это, но V - это частный вектор<> хранится в классе A, у которого есть средство доступа к нему, и я пытаюсь выполнить итерацию по нему в классе B, выполнив:
A->getV().begin(), A->getV().end(), etc..
У кого-нибудь есть хоть какое-то представление о том, что происходит?
Редактировать:Хорошо, поэтому я думаю, что лучше просто опубликовать код и указать, где могут возникнуть проблемы...
getTiles в GameState.h:
vector<vector<tile*>> getTiles();
for_each циклы в main.cpp:
for_each(currState->getTiles().begin(),currState->getTiles().end(), drawTiles);
.
.
void drawTiles(vector<tile*> row)
{
for_each(row.begin(), row.end(), dTile);
}
void dTile(tile *t)
{
t->draw();
}
создание векторов:
int tp = -1;
int bCounter = 0;
int wCounter = 0;
for (int i = 0; i < 8; i++)
{
vector<tile*> row(8);
for (int j = 0; j < 8; j++)
{
tile *t = new tile(tp, (i+(SIDELENGTH/2))*SIDELENGTH,
(j+(SIDELENGTH/2))*SIDELENGTH);
row.push_back(t);
tp *= -1;
}
currState->setTiles(row);
tp *= -1;
}
и на всякий случай, если это может иметь отношение к делу:
void gameState::setTiles(vector<tile*> val)
{
tiles.push_back(val);
}
Легче ли сейчас определить проблему?Я надеюсь на это...И если вы заметите какие-нибудь глупости, которые я, возможно, делаю, пожалуйста, дайте мне знать, я вроде как новичок в C ++, и указатели и ссылки все еще сбивают меня с толку.
РЕДАКТИРОВАТЬ 2:Спасибо, ребята, это сработало отлично...что ж, что касается этой проблемы, то теперь, похоже, у меня возникла проблема с созданием плиток и построением их в вектор строк..кажется, что даже несмотря на то, что вектор создан и передается правильно, плитки, которые должны были быть в нем, таковыми не являются (они теряются после :
for (int j = 0; j < 8; j++)
{
tile *t = new tile(tp, (i+(SIDELENGTH/2))*SIDELENGTH,
(j+(SIDELENGTH/2))*SIDELENGTH);
row.push_back(t);
tp *= -1;
}
петля.Если у кого-нибудь из вас есть хорошие идеи по решению этой проблемы, пожалуйста, помогите мне ;) Тем временем я буду продолжать пытаться это исправить
Решение
Для чего нужен прототип A::getV()
?
Я только предполагаю, но если A::getV()
не возвращает ссылку, тогда это может объяснить сообщение об ошибке "Векторные итераторы несовместимы".
В самом деле A->getV().begin()
и A->getV().end()
было бы два итератора по разным векторам:каждый A->getV()
вызов, возвращающий другую копию закрытого участника.
Надеюсь, это поможет вам отладить вашу проблему.
Редактировать:похоже, я правильно это предвидел:после редактирования вашего вопроса, содержащего подробную информацию, я вижу, что вы определяете
vector<vector<tile*> > getTiles();
Как следствие, в следующем заявлении:
for_each(currState->getTiles().begin(),currState->getTiles().end(), drawTiles);
Как и ожидалось выше, каждый вызов в getTiles()
вернет отдельную временную копию вектора-члена.Как следствие, итераторы вернулись из begin()
и end()
исходят из разных векторов, отсюда и сообщение об ошибке, с которым вы сталкиваетесь во время выполнения.
Кроме того, как указал Чарльз в своем подробном ответе, эти временные векторы будут уничтожены к тому времени , когда тело функции for_each
достигается.
Рассмотрите возможность возврата вектора по ссылке const следующим образом:
const vector<vector<tile*> >& getTiles() const;
И ты с таким же успехом можешь измениться drawTiles
чтобы избежать еще большего количества копий:
void drawTiles(const vector<tile*>& row)
Другие советы
То, что я делаю, это:прямой путь
vector<vector<int> > vvi;
vector<vector<int> >::iterator vvi_iterator;
vector<int>::iterator vi_iterator;
for(vvi_terator = vvi.begin();vvi_iterator!=vvi.end();++vvi_iterator) {
for(vi_iterator = (*vvi_iterator).begin();vi_iterator!=(*vvi_iterator).end();++vi _iterator) {
cout<<*vi_iterator<<" ";
}
}
Это приблизительная идея.Я нахожу метод for_each громоздким для простого выполнения двойного цикла.for_each полезно, когда вы действительно хотите выполнить некоторые вычисления для каждого элемента (например, какое-то отображение для каждого элемента)
У вас есть пара серьезных ошибок, но сначала одна незначительная.
vector<vector<tile*>> getTiles();
Пока не выйдет следующий стандарт, вам нужен пробел между >
.
vector< vector<tile*> > getTiles();
Эта функция возвращает vector
по значению, что означает, что он создает новую копию чего бы то ни было vector
передается оператору return в функции.(Я предполагаю, что это объявление функции является любым классом curState
является примером.)
Когда вы затем делаете:
for_each(currState->getTiles().begin(),currState->getTiles().end(), drawTiles);
Каждый вызов getTiles возвращает отдельную временную копию вектора.Это не только означает , что ваши итераторы из begin()
и end()
исходят из разностных векторов, но векторы будут уничтожены к тому времени, когда тело функции for_each
достигается.
Похоже, вам нужно исследовать ссылки и передавать по ссылке, потому что вам нужно понять их, прежде чем вы сможете правильно использовать std::for_each
в этих сценариях.