C++ STL Containers and references

c++, reference, stl

Solution

You can use a reference to assign to the object - by making the loop variable `o` a reference:

cout << "Increnting ... " << endl;
for (MyObject &o : oset)  o.value += 1000;

* EDIT *

But because set is an ordered container, it returns const iterators. So if you need to amend a set perhaps you should consider using another container instead. Perhaps a map?

But if you really have to change a set - don't do like the code below. It makes valgrind very upset, as Matthieu has pointed out. Why you can't go around erasing elements in a container whilst iterating through that container. Such madness leads to Undefined Behavior.

// ===== ATTENTION - NASTY CODE ALERT !! ========**
    for (MyObject &o : oset)
    {
        MyObject oNew = o;
        oNew.value += 1000;
        oset.erase(o);
        oset.insert(oNew);
    }
// =============================================**

A safer solution

would be to create another set, copy the original set (whilst applying the required changes), then swap the new set to the old one.

Here `transform` applies the lambda function over the entire set, and stores the results in the new `nset` set. `inserter` creates an insertion iterator for the nset container, inserting from nset.begin(). The final transform parameter - the lambda - takes an original set object and adds 1000 to it, returning the new object. Once the transform creates the new set, `swap` then places the new objects in the original container.

set<MyObject> nset;
transform(oset.begin(), oset.end(), inserter(nset, nset.begin()),
   [](const MyObject &o) { return MyObject (o.value+1000); });
oset.swap(nset);

See this question on set updates for more info.

Problem

I have a misunderstanding of how does work references, STL containers and Objects. I previously look for using references in an STL container, but it seems that STL containers are "objects that store objects". But if I want to store objects and modifying them in the container, how can i do it ? I pasted a small snipet of code illustrating my issue. ``` class MyObject { public : int value; MyObject(const MyObject& right) : value(right.value) {} MyObject(int _value) : value(_value) {} bool operator< (const MyObject& right) const { return value < right.value; } void display() const { cout << "(" << value << ") "; } }; ``` And in the main section ``` cout << "Creating ... " << endl; set<MyObject> oset; for (int i = 0 ; i < 10 ; i++) { MyObject o(rand() % 1000); oset.insert(o); } cout << endl; cout << "Display before ... " << endl; for (MyObject o : oset) o.display(); cout << endl; cout << "Incrementing ... " << endl; for (MyObject o : oset) o.value += 1000; cout << "Display after ... " << endl; for (MyObject o : oset) o.display(); cout << endl; ``` Since the container does not use references, the incrementation is applied on copies and not the objects. I tried to use '&' insided the loop i.e. ``` for (MyObject& o : oset) o.value += 1000; ``` but I had the following error : error: invalid initialization of reference of type ‘MyObject&’ from expression of type ‘const MyObject’

Original source

Related problems