Использование begin () и end () с набором в c ++ - PullRequest
1 голос
/ 30 августа 2011

Я пытаюсь использовать итератор, чтобы пройти через набор, а затем что-то сделать с членами этого набора (если они есть).Проблема в том, что обычно это работает, но иногда он сравнивает начало и конец пустого набора и находит, что они не равны.

Интересующий фрагмент кода:

    for(int i=0;i<input_data.num_particles();i++)
    {
        //loop through pairs contained in particle i's Verlet list
        set<int>::iterator iter;
        for(iter=verlet_vars.verlet()[i].begin();iter!=verlet_vars.verlet()[i].end();iter++)
        {
            //call the force() function to calculate the force between the particles
            force(particles.getpart(i),particles.getpart(*iter),input_data,*iter);  
        }
    }

Иногда, даже если набор, содержащийся в verlet_vars.verlet () [i], пуст, программа сравнивает итератор с концом набора и находит их не равными, и поэтому она входит во внутренний цикл (в конечном итоге вызываетсбой программы при попытке вызвать функцию force ().Что странно, если я что-то делаю с итератором до вызова внутреннего цикла, например, что-то вроде:

iter=verlet_vars.verlet()[i].begin();

, тогда сравнение для внутреннего цикла всегда возвращает true, и программа работает нормально.

PS команда verlet_vars.verlet () [i] вызывает вектор множеств, поэтому [i]

Функция verlet ():

std::vector<std::set<int> > verlet() const {return _verlet;}

Спасибоза ваше время.

Ответы [ 2 ]

8 голосов
/ 30 августа 2011

Ваша функция verlet_vars.verlet() возвращает значение, поэтому у вас есть два разных вектора наборов в игре. Сравнение итераторов двух разных контейнеров не определено. Это означает, что некоторые компоновки кода могут работать всегда, но вам все равно просто повезет, если это так.

Некоторые альтернативы:

  • Заставьте функцию возвращать ссылку на вектор вместо:

    std::vector<std::set<int> > const& verlet() const {return _verlet;}
    
  • Вызовите функцию один раз, чтобы получить локальную копию вектора (илинабор), а затем отработать локальную копию во время цикла:

    std::set<int> verlet_i = verlet_vars.verlet()[i];
    set<int>::iterator iter;
    for(iter=verlet_i.begin();iter!=verlet_i.end();iter++)
    
0 голосов
/ 30 августа 2011

Это может не иметь значения, в зависимости от того, копирует ли ваш компилятор или нет возвращаемое значение.Вы должны использовать константную ссылку для типа возврата verlet().Если нет, вы можете в конечном итоге получать различную копию с каждым вызовом, что (в зависимости от реализации) может привести к тому, что итераторы не будут сравниваться точно (например, сравнение итератора набора с конечным итератором другого набора, потому что каждыйкогда вы звоните verlet(), вы получаете другую копию набора.)

...