Изменение элементов в 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