Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to achieve better efficiency re-inserting into sets in C++

Tags:

c++

insert

set

stl

I need to modify an object that has already been inserted into a set. This isn't trivial because the iterator in the pair returned from an insertion of a single object is a const iterator and does not allow modifications. So, my plan was that if an insert failed I could copy that object into a temporary variable, erase it from the set, modify it locally and then insert my modified version.

insertResult = mySet.insert(newPep);
    if( insertResult.second == false )
        modifySet(insertResult.first, newPep);

void modifySet(set<Peptide>::iterator someIter, Peptide::Peptide newPep) {
    Peptide tempPep = (*someIter);
    someSet.erase(someIter);
    // Modify tempPep - this does not modify the key
    someSet.insert(tempPep);            

}

This works, but I want to make my insert more efficient. I tried making another iterator and setting it equal to someIter in modifySet. Then after deleting someIter I would still have an iterator to that location in the set and I could use that as the insertion location.

void modifySet(set<Peptide>::iterator someIter, Peptide::Peptide newPep) {
    Peptide tempPep = (*someIter);
    anotherIter = someIter;
    someSet.erase(someIter);
    // Modify tempPep - this does not modify the key
    someSet.insert(anotherIter, tempPep);            

}

However, this results in a seg fault. I am hoping that someone can tell me why this insertion fails or suggest another way to modify an object that has already been inserted into a set.

The full source code can be viewed at github.

like image 772
lashleigh Avatar asked Jun 21 '10 20:06

lashleigh


People also ask

What is the time complexity of set :: insert?

Its time complexity is O(logN) where N is the size of the set. insert(): insert a new element. Its time complexity is O(logN) where N is the size of the set. size(): Returns the size of the set or the number of elements in the set.

Is set or vector faster C++?

Vector is faster for insertion and deletion of elements at the end of the container. Set is faster for insertion and deletion of elements at the middle of the container.

How do you add value to a set?

The set::insert is a built-in function in C++ STL which insert elements in the set container or inserts the elements from a position to another position in the set to a different set. Parameters: The function accepts a mandatory parameter element which is to be inserted in the set container.

What does set insert return?

An insert operation on a set returns a pair, with its member first set to an iterator pointing to either the newly inserted element or to the equivalent element already in the set.


1 Answers

I agree with Peter that a map is probably a better model of what you are doing, specifically something like map<pep_key, Peptide::Peptide>, would let you do something like:

insertResult = myMap.insert(std::make_pair(newPep.keyField(), newPep));
if( insertResult.second == false )
    insertResult.first->second = newPep;  

To answer your question, the insert segfaults because erase invalidates an iterator, so inserting with it (or a copy of it) is analogous to dereferencing an invalid pointer. The only way I see to do what you want is with a const_cast

insertResult = mySet.insert(newPep);
if( insertResult.second == false )
    const_cast<Peptide::Peptide&>(*(insertResult.first)) = newPep;

the const_cast approach looks like it will work for what you are doing, but is generally a bad idea.

like image 61
academicRobot Avatar answered Oct 16 '22 13:10

academicRobot