push_back в список в цикле - PullRequest
0 голосов
/ 11 июля 2020

У меня проблема с перемещением элементов в QList при итерации по нему. Давайте посмотрим на пример кода ниже:

typedef struct
{
    int a[2];
} myType;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;

    QList<myType> list;

    // Create list
    for( int i = 0; i < 1000; i++)
    {
        list << (myType){ i, i };
    }

    int iteration = 0;

    for ( auto &i : list )
    {
        i.a[1] = 5;

        if ( ! (i.a[0] % 10) )
        {
            list.push_back( (myType){ 7, 7 } );
        }
        iteration++;
    }

    w.show();
    return a.exec();
}

Когда я отлаживаю код, у меня возникает ошибка сегментации (i получено значение 0xfeeefeeefeeefeee):

введите описание изображения здесь

В чем причина?

Ответы [ 2 ]

1 голос
/ 11 июля 2020

Причина ошибки сегментации заключается в том, что изменение размера контейнера, который вы перебираете в цикле в диапазоне for l oop, является неопределенным поведением. Таким образом, l oop необходимо переписать.

Глядя на ваш код, вы все равно можете использовать ранжированный for, но не изменять список. Следующий код кажется эквивалентным (но не протестирован):

int numExtra = 0;
for ( auto &i : list )
{
    i.a[1] = 5;

    if ( ! (i.a[0] % 10) )
        ++numExtra;
    iteration++;
}

for (int i = 0; i < numExtra; ++i)
    list.push_back( (myType){ 7, 7 } );

Поскольку значение, добавляемое в список, является тем же значением, код просто подсчитывает количество возможных push_back вызовов, которые будут быть вызванным. После завершения начального l oop мы просто вызываем push_back всего numExtra раз.

0 голосов
/ 11 июля 2020

Если вы используете итератор for l oop, это все равно будет работать, если вы только добавляете в список:

for ( auto it = list.begin(); it != list.end(); ++it )
{
    it->a[1] = 5;

    if ( ! (it->a[0] % 10) )
    {
        list.push_back( myType({ 7, 7 }) );
    }
    iteration++;
}

С диапазоном for, list.end() оценивается только один раз в начале и становится недействительным при вставке нового элемента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...