Делает pop_back (), действительно делают недействительным *все* итераторы на станд.:: вектор?

Я работаю в Android Studio и столкнулся с этой ошибкой при попытке создать подписанный APK для выпуска. Мне удалось создать и протестировать отладочную APK без проблем, но как только я захочу создать APK выпуска, процесс сборки будет работать в течение нескольких минут подряд, а затем окончательно завершится с помощью «Ошибка java.lang.OutOfMemoryError: GC превышение верхнего предела ". Я увеличил размеры кучи как для VM, так и для компилятора Android DEX, но проблема не устранена. Наконец, после многих часов и кружек кофе выяснилось, что проблема была в моем файле buildGradle на уровне приложения. У меня был параметр minifyEnabled для типа сборки релиза, установленного на «ложь», и, следовательно, работа с продуктами Proguard по коду, который не прошел через процесс сжатия кода (см. https://developer.android.com/studio/build/shrink-code.html ). Я изменил параметр «minifyEnabled» на «true», а сборка релиза была выполнена как сон:)

. Короче, мне пришлось изменить файл «build.gradle» на уровне приложения из: //. ..

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.sign_config_release
    }
    debug {
        debuggable true
        signingConfig signingConfigs.sign_config_debug
    }
}

//...

-

    //...

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.sign_config_release
    }
    debug {
        debuggable true
        signingConfig signingConfigs.sign_config_debug
    }
}

//...

5
задан adl 21 February 2012 в 15:47
поделиться

11 ответов

Вызов к pop_back() удаляет последний элемент в векторе и таким образом, итератор к тому элементу делается недействительным. pop_back() вызов не делает недействительным итераторы к объектам перед последним элементом, только перераспределение сделает это. Из "Справочного руководства по библиотеке Стандарта C++ Josuttis":

Элементы вставки или удаления делают недействительным ссылки, указатели и итераторы, которые обращаются к следующему элементу. Если вставка вызывает перераспределение, она делает недействительным все ссылки, итераторы и указатели.

12
ответ дан 18 December 2019 в 05:37
поделиться

Вот Ваш ответ, непосредственно из Святого Стандарта:

23.2.4.2 Вектор удовлетворяет все требования контейнера и обратимого контейнера (данный в двух таблицах в 23,1) и последовательности, включая большинство дополнительных требований последовательности (23.1.1).
23.1.1.12 Таблица 68 expressiona.pop_back () возвращает typevoid операционный semanticsa.erase (-a.end ()) containervector, список, двухсторонняя очередь

Заметьте что pop_back эквивалентного a.erase (-a.end ()). Рассмотрение специфических особенностей вектора стирания:

23.2.4.3.3 - стирание итератора (положение итератора) - эффекты - Делает недействительным все итераторы и ссылки после точки стирания

Поэтому, после того как Вы называете pop_back, любые итераторы к ранее заключительному элементу (который теперь больше не существует), делаются недействительным.

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

12
ответ дан 18 December 2019 в 05:37
поделиться

(Я использую нумерацию, как используется в C++ 0x работающий проект, доступный здесь

Таблица 94 на уровне страницы 732 говорит, что pop_back (если это существует в контейнере последовательности) имеет следующий эффект:

{ iterator tmp = a.end(); 
--tmp; 
a.erase(tmp); } 

23.1.1, укажите на 12 состояний что:

Если иначе specified (или явно или defining функция с точки зрения других функций), вызывая контейнерную функцию членства или передавая контейнер как аргумент библиотечной функции не буду делать недействительным итераторы к или изменять значения, объекты в том контейнере.

Оба конца доступа () как применение префикса - не имеют такого эффекта, стирание () однако:

23.2.6.4 (относительно vector.erase () указывают 4):

Эффекты: Делает недействительным итераторы и ссылки в или после точки стирания.

Таким образом в заключении: pop_back () будет только делать недействительным итератор к последнему элементу на стандарт.

4
ответ дан 18 December 2019 в 05:37
поделиться

Вот кавычка из документации STL SGI (http://www.sgi.com/tech/stl/Vector.html):

[5] Итераторы вектора делаются недействительным, когда его память перераспределена. Кроме того, вставка или удаление элемента посреди вектора делают недействительным все итераторы, которые указывают на элементы после точки удаления или вставки. Из этого следует, что можно препятствовать тому, чтобы итераторы вектора делались недействительным, при использовании резерва () для предварительного выделения такой памяти, как вектор будет когда-либо использовать, и если все вставки и удаления в конце вектора.

Я думаю из этого следует, что pop_back только делает недействительным итератор, указывающий на последний элемент и конец () итератор. Мы действительно должны видеть данные, для которых код перестал работать, а также способ, которым этому не удается решить то, что продолжается. Насколько я могу сказать, код должен работать - обычная проблема в таком коде состоит в том, что удаление элемента и ++ на итераторе происходит в том же повторении, указывает путь @mikhaild. Однако в этом коде это не имеет место: этого ++ не происходит, когда pop_back называют.

Что-то плохо может все еще произойти, когда это указывает на последний элемент, и последний элемент - меньше чем 10. Мы теперь сравниваем недействительное это и конец (). Это может все еще работать, но никакие гарантии не могут быть сделаны.

3
ответ дан 18 December 2019 в 05:37
поделиться

Итераторы только делаются недействительным на перераспределении устройства хранения данных. Google является Вашим другом: см. сноску 5.

Ваш код не работает по другим причинам.

1
ответ дан 18 December 2019 в 05:37
поделиться

pop_back() делает недействительным только итераторы, которые указывают на последний элемент. Из Справочного руководства по библиотеке Стандарта C++:

Элементы вставки или удаления делают недействительным ссылки, указатели и итераторы, которые обращаются к следующему элементу. Если вставка вызывает перераспределение, она делает недействительным все ссылки, итераторы и указатели.

Таким образом для ответа на вопрос нет это не делает недействительным все итераторы.

Однако в Вашем примере кода, это может делать недействительным it когда это указывает на последний элемент, и значение ниже 10. В этом случае отладка Visual Studio, STL отметит итератор, как делается недействительным и дальнейшую проверку на него не являющийся равным концу () покажет утверждение.

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

1
ответ дан 18 December 2019 в 05:37
поделиться

Ошибка состоит в том, что, когда "это" указывает на последний элемент вектора и если этот элемент - меньше чем 10, этот последний элемент удален. И теперь "это" указывает на ints.end (), затем "это ++" указатель перемещений на ints.end () +1, поэтому теперь "это" убегающий из ints.end (), и Вы получили бесконечный цикл, сканируя всю Вашу память :).

0
ответ дан 18 December 2019 в 05:37
поделиться

"Официальной спецификацией" является Стандарт C++. Если у Вас нет доступа к копии C++ 03, можно получить последний проект C++ 0x с веб-сайта Комитета: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2723.pdf

Раздел "Operational Semantics" контейнерных требований указывает, что pop_back () эквивалентен {итератор i = конец (); - я; стирание (i);}. [vector.modifiers] раздел для стирания говорит "Эффекты: Делает недействительным итераторы и ссылки в или после точки стирания".

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

0
ответ дан 18 December 2019 в 05:37
поделиться

pop_back () будет только делать недействительным его, если это указывало на последний объект в векторе. Ваш код поэтому перестанет работать каждый раз, когда последний интервал в векторе - меньше чем 10, следующим образом:

*это = ints.back ();//Набор *это к значению это уже имеет
ints.pop_back ();//Делают недействительным итератор
продолжите;//Цикл вокруг и доступ недопустимый итератор

0
ответ дан 18 December 2019 в 05:37
поделиться

Проверьте информацию здесь (cplusplus.com):

Удалите последний элемент

Удаляет последний элемент в векторе, эффективно уменьшая векторный размер одним и делая недействительным все итераторы и ссылки на него.

-1
ответ дан 18 December 2019 в 05:37
поделиться

Вы могли бы хотеть рассмотреть использование возвращаемого значения стирания вместо того, чтобы подкачать задний элемент к удаленной позиции сование назад. Для последовательностей стирание возвращает итератор, указывающий элемент один вне удаляемого элемента. Обратите внимание, что этот метод может вызвать больше копирования, чем Ваш исходный алгоритм.

for(std::vector<int>::iterator it = ints.begin(); it != ints.end(); )
{
    if(*it < 10)
        it = ints.erase( it );
    else
        ++it;
}

std::remove_if могло также быть альтернативное решение.

struct LessThanTen { bool operator()( int n ) { return n < 10; } };

ints.erase( std::remove_if( ints.begin(), ints.end(), LessThanTen() ), ints.end() );

std::remove_if (как мой первый алгоритм) стабилен, таким образом, это не может быть самый эффективный способ сделать это, но это сжато.

0
ответ дан 18 December 2019 в 05:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: