Изменение элементов в std:: set
У меня есть следующий код -:
int main()
{
set<string> s;
s.insert( "asas" );
s.insert( "abab" );
for ( auto item : s )
{
cout << item << "n";
reverse( item.begin(), item.end() );
}
cout << "n";
for ( auto item : s )
{
cout << item << "n";
}
}
Вывод -:
abab
asas
abab
asas
Элементы множества вообще не модифицируются функцией reverse().
Я подозреваю, что элементы внутри набора вообще не могут быть изменены. Но если это так, то почему компилятор не выдает ошибку в первую очередь сам ?
Я использую TDM-GCC 4.9.2 с флагом -std=c++14 в Windows 7.
3 ответа:
Элементами a
std::setявляютсяconst. Если вы хотите изменить элементы, вам нужно выполнить вставки и удаления, чтобы поместить контейнер в нужное состояние.В примере кода:
for (auto item : s)Переводится примерно так:
for (auto iter = s.begin(); iter != s.end(); ++iter) { auto item = *iter; // Copy! // loop body }Переменная индукции цикла
itemявляетсякопией элемента изset, а не ссылкой на фактический элемент вset. В результатеsetне изменяется. Чтобы изменить набор, необходимо вызвать функцию-член изset, напримерinsertилиerase.Изменение
itemна&itemздесь не поможет; если вы сделаете это, вы получите ошибку компиляции, потому что элементы набора являются const, поэтому вы не можете применитьreverseк ним.
Этот цикл на основе диапазона создает копии каждого элемента в наборе:
Именно поэтому вы можете изменятьfor ( auto item : s )itemв цикле, не вызывая ошибки компилятора.Если вы хотите изменить элементы контейнера, вам понадобится ссылка. Использование этого действительно приведет к ошибке компилятора, потому что элементы набора не могут быть изменены:
for ( auto& item : s ) { // s is a set. You cannot modify item