C ++: перебор вектора векторов - PullRequest
1 голос
/ 28 ноября 2009

Привет! Я делаю этот проект и сейчас пытаюсь:

  1. создает некоторые объекты и сохраняет их в векторах, которые сохраняются в другом векторе V
  2. перебирать векторы внутри V
  3. перебирать объекты внутри отдельных векторов

В любом случае, я просто искал в Интернете и наткнулся на функцию stl for_each. Это кажется довольно опрятным, но у меня есть проблемы с этим. Я пытаюсь использовать это так:

for_each(V.begin(), V.end(), iterateThroughSmallVectors);

iterateThroug .... просто делает то же самое с вектором, переданным ему ..

Теперь я получаю странную ошибку "несовместимые векторные итераторы". Я посмотрел на это и не могу найти какой-либо полезной информации об этом ..

Я не знаю, помогает ли это, но 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 ++, а указатели и ссылки все еще смущают меня.

EDIT2: Спасибо, ребята, это отлично сработало ... хорошо для этой проблемы, теперь, кажется, у меня есть проблема с созданием плиток и нанесением их на вектор строки ... кажется, что даже через вектор создан и проходит правильно, плитки, которые должны были быть в нем, отсутствуют (они теряются после:

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

петля. Если у кого-то из вас есть какие-либо хорошие идеи по решению этой проблемы, вы можете мне помочь;) А пока я буду пытаться это исправить

Ответы [ 3 ]

7 голосов
/ 28 ноября 2009

Какой прототип для 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 vector<vector<tile*> >& getTiles() const;

И вы также можете изменить drawTiles, чтобы избежать еще большего количества копий:

void drawTiles(const vector<tile*>& row)

4 голосов
/ 28 ноября 2009

Что я делаю, так это: прямой путь

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 полезен, когда вы действительно хотите выполнить некоторые вычисления для каждого элемента (например, какое-то отображение для каждого элемента)

2 голосов
/ 28 ноября 2009

У вас есть пара серьезных ошибок, но сначала небольшая.

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 в этих сценариях.

...