2015-07-01 2 views
2

Я следующий код -:Изменение элементов в станд :: набор

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.

+1

Вы работаете с копиями элементов, оригиналы в 'set' не изменяются. Используйте итераторы, чтобы манипулировать ими напрямую. –

+0

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

ответ

5

Элементы std::setconst являются. Если вы хотите мутировать элементы, вам нужно сделать вставки и удаления, чтобы поместить контейнер в нужное состояние.

В вашем примере кода:

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 здесь не поможет; если вы это сделаете, вы получите ошибку времени компиляции, потому что элементы набора являются константами, поэтому вы не можете применить к ним reverse.

2

Этот диапазон делает копии каждого элемента в наборе:

for (auto item : s) 

Вот почему вы можете изменить item в цикле без запуска ошибки компилятора.

Если вы хотите изменить элементы контейнера, вам нужна ссылка. Используя это было на самом деле приведет к ошибке компиляции, поскольку элементы множества не могут быть изменены:

for (auto& item : s) 
{ 
    // s is a set. You cannot modify item 
0

Объекты в std :: set являются константами, так как они используются как ключи. Поэтому вы не можете изменять объекты в таком наборе.