How to change object child members in a set

2019-07-08 09:42发布

问题:

I am using a set to hold objects. I want to make changes to the first object in the set. This is what I tried:

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

This is the error I get:

error: read-only variable is not assignable

How did the variable become read-only? How can it be changed?

回答1:

The things in a set are effectively read-only - you cannot change the value of a member of a set in situ. All you can do is remove it, and add a new member with the required new value. This restriction is necessary because of the binary tree implementation of std::set.



回答2:

If you really have to modify the element in set, the element has to be once erased from the set and re-inserted in that set.
For example:

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

If operator< for myClass doesn't refer the value member, you can use std::map instead of set. Assuming a new myClass which doesn't have value member, and assuming that the type of value member is T, then std::map< newMyClass, T > will meet the purpose.



回答3:

This compiles under VS2008:

#include <set>

struct myClass{
    int value;
    int comp;
};

bool operator<(const myClass& lhs,const myClass& 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;
}

But this only works by coincidence. operator< compares the comp members and we change the value member.



回答4:

in Visual Studio 2010 when Microsoft updated the STL, they made all iterators constant. So set::iterator and set::const_iterator are the same.

The reason is because in a set, the key is the data itself, and when you change your data, and thus the key, which is a no no.

The microsoft C++ team reported on this breaking change here: http://blogs.msdn.com/b/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx

If you want to be modifying your data, and don't want to be removing and inserting, then use a map instead.