Почему std :: set.insert () возвращает неконстантный итератор, и все же я не могу его изменить? - PullRequest
13 голосов
/ 12 апреля 2011

Рассмотрим пример кода:

#include <set>
#include <string>

using namespace std;

set<string> string_set;

void foo(const string& a)
{
    pair<set<string>::iterator, bool> insert_result = string_set.insert(a);

    string& val = *(insert_result.first);
    val += " - inserted";
}

Итак, за исключением правильности, такой как не проверка на успешную вставку и т. Д., Этот код выглядит так, как будто он должен позволять мне изменять строку после вставки, но компилятор (VS2010) запрещает разыменовывать итератор в неконстантную строку (мы мигрируем с VS2005, который прошел без предупреждения).

Теперь я знаю, что это следует запретить, так как это может сделать строку неуникальной, и я отчасти рад, что она работает таким образом, но в реальном случае это не так ясно, как это, так как я хотите изменить неизменяемый элемент данных, который не участвует в проверке эквивалентности или упорядочении.

Что я хочу знать, так это как компилятор ЗНАЕТ, что мне не разрешено это делать, и как я могу узнать без ссылки на документацию (которая в любом случае не упоминает об этом)?

Ура, Guy

Ответы [ 2 ]

24 голосов
/ 12 апреля 2011

Поскольку согласно стандарту, модификации через set<>::iterator не допускаются.Стандарт, в частности, разрешает использовать set<>::iterator и set<>::const_iterator одного типа.И хотя он не требует, чтобы они были одного типа, он требует, чтобы value_type из set<>::iterator было const.

Причина этого, конечно, заключается в том, что любые модификациизначение может сделать недействительными инварианты std::set<>.

3 голосов
/ 12 апреля 2011

Из стандарта:

23,3,3

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

Это тоже из стандарта:
определена реализация typedef итератор; // см. 23.1

Реальная реализация set :: iterator является постоянным итератором, чтобы сохранить требование иметь уникальные ключи. В противном случае вы можете изменить значения в наборе на все те же значения.

...