Как изменить дочерние элементы объекта в наборе

#c #class #object #set

#c #класс #объект #набор

Вопрос:

Я использую набор для хранения объектов. Я хочу внести изменения в первый объект в наборе. Это то, что я пробовал:

 set<myClass>::iterator i = classlist.begin();
i->value = 0;
  

Это ошибка, которую я получаю:

 error: read-only variable is not assignable
  

Как переменная стала доступной только для чтения? Как это можно изменить?

Комментарии:

1. Пожалуйста, расскажите нам, что classlist такое.

2. classlist — это набор, содержащий объекты MyClass.

3. ошибка, извините, что такое myClass ? Более конкретно, как он определяет operator< ?

4. Я перегружаю оператор < для набора вне MyClass, чтобы MyClass можно было добавить в набор.

Ответ №1:

Объекты в наборе фактически доступны только для чтения — вы не можете изменить значение элемента набора на месте. Все, что вы можете сделать, это удалить его и добавить новый элемент с требуемым новым значением. Это ограничение необходимо из-за реализации std::set в двоичном дереве.

Комментарии:

1. Существуют ли какие-либо другие контейнеры, похожие на set, которые не доступны только для чтения?

2. Да, аналогичным образом вы не можете изменить ключи map.

Ответ №2:

Если вам действительно нужно изменить элемент в set , элемент должен быть один раз удален из set и повторно вставлен в это set .
Например:

 set<myClass>::iterator i = classlist.begin();
myClass c = *i;
c.value = 0;
classlist.erase( i );
classlist.insert( c );
  

Если operator< for myClass не ссылается на value элемент,
вы можете использовать std::map вместо set .
Предполагая, что новый, myClass у которого нет value элемента,
и предполагая, что тип value элемента T равен,
тогда std::map< newMyClass, T > будет соответствовать цели.

Комментарии:

1. Вы не можете изменить ключи в map.

2. @unapersson: Спасибо за комментарий. Однако, извините, я не вижу особого отношения комментария к ответу. В приведенном выше ответе не говорится об изменении ключа в map .

Ответ №3:

Это компилируется под VS2008:

 #include <set>

struct myClass{
    int value;
    int comp;
};

bool operator<(const myClassamp; lhs,const myClassamp; rhs){
    return lhs.comp<rhs.comp;
}

int main(){

    std::set<myClass> classlist;
    myClass c;
    classlist.insert(c);

    std::set<myClass>::iterator i=classlist.begin();
    i->value=0;

    return 0;
}
  

Но это работает только по совпадению. operator< сравнивает comp элементы, и мы меняем value элемент.

Комментарии:

1. Это не компилируется в GCC.

Ответ №4:

в Visual Studio 2010, когда Microsoft обновила STL, они сделали все итераторы постоянными. Итак, set::iterator и set::const_iterator — это одно и то же.

Причина в том, что в наборе ключом являются сами данные, и когда вы меняете свои данные и, следовательно, ключ, который является no no.

Команда Microsoft C сообщила об этом решающем изменении здесь: http://blogs.msdn.com/b/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx

Если вы хотите изменять свои данные и не хотите удалять и вставлять, то вместо этого используйте map.