#c 11
#c 11
Вопрос:
Ниже приведен код:
vector<set<int>> sets;
set<int> myset{ 3, 5, 8, 2, 10, 9, 7, 15 };
set<int> newSet{ *myset.begin() };
sets.push_back(newSet);
set<int>::iterator it = myset.begin();
it ;
for (; it != myset.end(); it )
{
for (vector<set<int>>::iterator it1 = sets.begin(); it1 != sets.end(); it1 )
{
set<int> newSet1(*it1); //LINE1
sets.push_back(newSet1); //LINE2
it1->insert(*it); //LINE3
}
}
Во время первого ввода во второй цикл for, после LINE2
, it1
становится НУЛЕВЫМ, поэтому LINE3
вызывает segmentation fault
. Почему после LINE2
, it1
исчез?
LINE2
копирует newSet1
в векторные наборы. Будет ли он копировать весь набор или только адрес newSet1
?
Ответ №1:
Давайте возьмем подмножество вашего кода:
std::vector<T> sets;
for (auto it = sets.begin(); it != sets.end(); it )
sets.emplace_back();
Приведенный выше код демонстрирует неопределенное поведение, потому что мы модифицируем вектор, а затем ожидаем, что итераторы sets
все еще действительны.
В частности, итераторы станут недействительными при выполнении insert()
и size() == capacity()
.
По поводу вашего другого вопроса:
СТРОКА 2 копирует newSet1 в наборы векторов. Будет ли он копировать весь набор или только адрес newSet1?
Он вызовет конструктор копирования std::set<T>
, и вы получите копию набора, который вы передали в качестве аргумента для push_back()
вызова.
Ответ №2:
Push_back изменяет наборы, поэтому it1 больше не является надежным. Push_back копирует всю запись в вектор.
Доступ к вектору через индекс (например, sets[2] ) будет работать, но границы не проверяются, поэтому перед доступом убедитесь, что индекс находится в пределах диапазона.
Комментарии:
1. Это слишком жутко. 🙁 Предполагается, что push_back создает только копию newSet1. Почему он уничтожает newSet1?
2. Это не так. Это не уничтожает запись, которая помещена в вектор.
3. @John это не уничтожает
newSet1
, а делает недействительнымit1
. Это происходит послеpush_back
того, как итераторit1
указывает на неправильное местоположение, и это вызывает неопределенное поведение, в вашем случае segfault.4. it1 ненадежен, потому что push_back может полностью изменить вектор. (Он может быть скопирован в другую область памяти для обработки более длинного массива. Бесплатных обедов нет даже в STL.)
5. Что мне нужно, так это изменить вектор во время итерации вектора. Нет никакого способа сделать это с помощью итератора, верно? Как насчет использования «для цикла диапазона»? например, ‘for(auto e : vec) {std::set e1(e); vec.puch_back(e1); }’. Будет ли это работать?