I've got code that looks like this:
for (std::list<item*>::iterator i=items.begin();i!=items.end();i++)
{
bool isActive = (*i)->update();
//if (!isActive)
// items.remove(*i);
//else
other_code_involving(*i);
}
items.remove_if(CheckItemNotActive);
I'd like remove inactive items immediately after update them, inorder to avoid walking the list again. But if I add the commented-out lines, I get an error when I get to i++: "List iterator not incrementable". I tried some alternates which didn't increment in the for statement, but I couldn't get anything to work.
What's the best way to remove items as you are walking a std::list?
You have to increment the iterator first (with i++) and then remove the previous element (e.g., by using the returned value from i++). You can change the code to a while loop like so:
std::list<item*>::iterator i = items.begin();
while (i != items.end())
{
bool isActive = (*i)->update();
if (!isActive)
{
items.erase(i++); // alternatively, i = items.erase(i);
}
else
{
other_code_involving(*i);
++i;
}
}
You want to do:
i= items.erase(i);
That will correctly update the iterator to point to the location after the iterator you removed.
You need to do the combination of Kristo's answer and MSN's:
// Note: Using the pre-increment operator is preferred for iterators because
// there can be a performance gain.
//
// Note: As long as you are iterating from beginning to end, without inserting
// along the way you can safely save end once; otherwise get it at the
// top of each loop.
std::list< item * >::iterator iter = items.begin();
std::list< item * >::iterator end = items.end();
while (iter != end)
{
item * pItem = *iter;
if (pItem->update() == true)
{
other_code_involving(pItem);
++iter;
}
else
{
// BTW, who is deleting pItem, a.k.a. (*iter)?
iter = items.erase(iter);
}
}
Of course, the most efficient and SuperCool® STL savy thing would be something like this:
// This implementation of update executes other_code_involving(Item *) if
// this instance needs updating.
//
// This method returns true if this still needs future updates.
//
bool Item::update(void)
{
if (m_needsUpdates == true)
{
m_needsUpdates = other_code_involving(this);
}
return (m_needsUpdates);
}
// This call does everything the previous loop did!!! (Including the fact
// that it isn't deleting the items that are erased!)
items.remove_if(std::not1(std::mem_fun(&Item::update)));
I have sumup it, here is the three method with example:
1. using while loop
list<int> lst{4, 1, 2, 3, 5};
auto it = lst.begin();
while (it != lst.end()){
if((*it % 2) == 1){
it = lst.erase(it);// erase and go to next
} else{
++it; // go to next
}
}
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
2. using remove_if member funtion in list:
list<int> lst{4, 1, 2, 3, 5};
lst.remove_if([](int a){return a % 2 == 1;});
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
3. using std::remove_if funtion combining with erase member function:
list<int> lst{4, 1, 2, 3, 5};
lst.erase(std::remove_if(lst.begin(), lst.end(), [](int a){
return a % 2 == 1;
}), lst.end());
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
4. using for loop , should note update the iterator:
list<int> lst{4, 1, 2, 3, 5};
for(auto it = lst.begin(); it != lst.end();++it){
if ((*it % 2) == 1){
it = lst.erase(it); erase and go to next(erase will return the next iterator)
--it; // as it will be add again in for, so we go back one step
}
}
for(auto it:lst)cout<<it<<" ";
cout<<endl; //4 2
Use std::remove_if algorithm.
Edit:
Work with collections should be like:
prepare collection.
process collection.
Life will be easier if you won't mix this steps.
std::remove_if. or list::remove_if ( if you know that you work with list and not with the TCollection )
std::for_each
The alternative for loop version to Kristo's answer.
You lose some efficiency, you go backwards and then forward again when deleting but in exchange for the extra iterator increment you can have the iterator declared in the loop scope and the code looking a bit cleaner. What to choose depends on priorities of the moment.
The answer was totally out of time, I know...
typedef std::list<item*>::iterator item_iterator;
for(item_iterator i = items.begin(); i != items.end(); ++i)
{
bool isActive = (*i)->update();
if (!isActive)
{
items.erase(i--);
}
else
{
other_code_involving(*i);
}
}
Here's an example using a for loop that iterates the list and increments or revalidates the iterator in the event of an item being removed during traversal of the list.
for(auto i = items.begin(); i != items.end();)
{
if(bool isActive = (*i)->update())
{
other_code_involving(*i);
++i;
}
else
{
i = items.erase(i);
}
}
items.remove_if(CheckItemNotActive);
Removal invalidates only the iterators that point to the elements that are removed.
So in this case after removing *i , i is invalidated and you cannot do increment on it.
What you can do is first save the iterator of element that is to be removed , then increment the iterator and then remove the saved one.
If you think of the std::list like a queue, then you can dequeue and enqueue all the items that you want to keep, but only dequeue (and not enqueue) the item you want to remove. Here's an example where I want to remove 5 from a list containing the numbers 1-10...
std::list<int> myList;
int size = myList.size(); // The size needs to be saved to iterate through the whole thing
for (int i = 0; i < size; ++i)
{
int val = myList.back()
myList.pop_back() // dequeue
if (val != 5)
{
myList.push_front(val) // enqueue if not 5
}
}
myList will now only have numbers 1-4 and 6-10.
Iterating backwards avoids the effect of erasing an element on the remaining elements to be traversed:
typedef list<item*> list_t;
for ( list_t::iterator it = items.end() ; it != items.begin() ; ) {
--it;
bool remove = <determine whether to remove>
if ( remove ) {
items.erase( it );
}
}
PS: see this, e.g., regarding backward iteration.
PS2: I did not thoroughly tested if it handles well erasing elements at the ends.
You can write
std::list<item*>::iterator i = items.begin();
while (i != items.end())
{
bool isActive = (*i)->update();
if (!isActive) {
i = items.erase(i);
} else {
other_code_involving(*i);
i++;
}
}
You can write equivalent code with std::list::remove_if, which is less verbose and more explicit
items.remove_if([] (item*i) {
bool isActive = (*i)->update();
if (!isActive)
return true;
other_code_involving(*i);
return false;
});
The std::vector::erase std::remove_if idiom should be used when items is a vector instead of a list to keep compexity at O(n) - or in case you write generic code and items might be a container with no effective way to erase single items (like a vector)
items.erase(std::remove_if(begin(items), end(items), [] (item*i) {
bool isActive = (*i)->update();
if (!isActive)
return true;
other_code_involving(*i);
return false;
}));
do while loop, it's flexable and fast and easy to read and write.
auto textRegion = m_pdfTextRegions.begin();
while(textRegion != m_pdfTextRegions.end())
{
if ((*textRegion)->glyphs.empty())
{
m_pdfTextRegions.erase(textRegion);
textRegion = m_pdfTextRegions.begin();
}
else
textRegion++;
}
I'd like to share my method. This method also allows the insertion of the element to the back of the list during iteration
#include <iostream>
#include <list>
int main(int argc, char **argv) {
std::list<int> d;
for (int i = 0; i < 12; ++i) {
d.push_back(i);
}
auto it = d.begin();
int nelem = d.size(); // number of current elements
for (int ielem = 0; ielem < nelem; ++ielem) {
auto &i = *it;
if (i % 2 == 0) {
it = d.erase(it);
} else {
if (i % 3 == 0) {
d.push_back(3*i);
}
++it;
}
}
for (auto i : d) {
std::cout << i << ", ";
}
std::cout << std::endl;
// result should be: 1, 3, 5, 7, 9, 11, 9, 27,
return 0;
}
I think you have a bug there, I code this way:
for (std::list<CAudioChannel *>::iterator itAudioChannel = audioChannels.begin();
itAudioChannel != audioChannels.end(); )
{
CAudioChannel *audioChannel = *itAudioChannel;
std::list<CAudioChannel *>::iterator itCurrentAudioChannel = itAudioChannel;
itAudioChannel++;
if (audioChannel->destroyMe)
{
audioChannels.erase(itCurrentAudioChannel);
delete audioChannel;
continue;
}
audioChannel->Mix(outBuffer, numSamples);
}
I have defined a base class using std::thread. For the child class, I perform some initialization of member variables and then start the thread using m_thread.reset(new std::thread(&MyClass::ThreadMain, this)); where m_thread is a member of MyClass. The purpose of the class is to read data from a serial port and report to a parent. The posix message queue handle of the parent is passed to MyClass during initialization before the thread is created. On running I get exceptions and I see that member variables that were initialized before the thread started appear to be no longer valid using the watch in GDB.
It appears as if the first message on the serial port is received and passed validation in order to get to the SendToParent call. At this call, it appears that I lose the stack. I tried running cppcheck to see if I have any memory leaks or buffer overflows and found nothing.
void MyClass::ThreadMain(void)
{
ssize_t bytesRead = 0;
UINT8 buffer[256];
UINT8 message[256];
BOOL partialMessage = FALSE;
UINT8 messageIndex = 0;
UINT8 payloadLength = 0;
// read data from the UART
while(1)
{
// the UART is setup to pend until data is available
bytesRead = read(m_radioFileDescriptor, buffer, sizeof(buffer));
if (FAIL == bytesRead)
{
LOG_SYSTEM_INFO("UART Read interrupted by a system call");
}
else if (bytesRead > 0)
{
// build the message
for(ssize_t i = 0 ; i < bytesRead ; i++)
{
if (FALSE == partialMessage)
{
// have we found the start of the message?
if(START_BYTE == buffer[i])
{
// start of new message
messageIndex = 0;
message[messageIndex] = buffer[i];
partialMessage = TRUE;
messageIndex++;
}
}
else
{
// keep building the message until the expected length is reached
if(LENGTH_POSITION == messageIndex)
{
// capture the expected message length
message[messageIndex] = buffer[i];
messageIndex++;
payloadLength = buffer[i];
}
else
{
message[messageIndex] = buffer[i];
messageIndex++;
// check for expected length and end byte
if((messageIndex == payloadLength) && (END_BYTE == buffer[i]))
{
// this should be a valid message but need to confirm by checking for a valid checksum
UINT8 messageChecksum = message[messageIndex - CHKSUM_POS_FROM_END];
UINT8 calculatedChecksum = RadioProtocol::Instance().GenerateRadioChecksum(message, (payloadLength - CHKSUM_POS_FROM_END));
if (messageChecksum == calculatedChecksum)
{
SendToParent(message, payloadLength);
}
else
{
LOG_SYSTEM_ERROR("Checksum FAILURE");
}
// reset for the next message
partialMessage = FALSE;
messageIndex = 0;
}
else if((messageIndex == payloadLength) && (END_BYTE != buffer[i]))
{
// malformed message - throw out and look for start of next message
LOG_SYSTEM_ERROR("Bytes read exceeded expected message length");
partialMessage = FALSE;
messageIndex = 0;
}
}
}
} // end for loop of bytes read on the port
}
else
{
LOG_SYSTEM_INFO("Read returned 0 bytes which is unexpected");
}
}
}
void MyClass::SendToParent(UINT8* pMsg, UINT8 size)
{
if ((pMsg != NULL) && (m_parentQueueHandle > 0))
{
// message is valid - pass up for processing
MsgQueueMessage msgToSend;
msgToSend.m_msgHeader = UART_MESSASGE;
bzero(msgToSend.m_msgData, sizeof(msgToSend.m_msgData));
for (UINT8 i = 0; i < size; i++)
{
msgToSend.m_msgData[i] = pMsg[i];
}
if (FAIL == msgsnd(m_parentQueueHandle, &msgToSend, sizeof(msgToSend), IPC_NOWAIT))
{
LOG_SYSTEM_ERROR("FAILED to send message on queue");
}
}
}
This acts like I am performing a buffer overflow but I just can't see it. When I set a breakpoint at the line UINT8 messageChecksum = message[messageIndex - CHKSUM_POS_FROM_END]; all data in the watch window appear valid. If I step over to the next line then the data, m_parentQueueHandle as an example, gets blown away.
This is my first time working with c++11 threads and particularly with c++. Any help or insights would be appreciated.
I think I found the issue. I added a bunch of printfs and found that the destructor for the class was being called. Much further upstreamI had the parent object being created as a local variable and it was going out of scope. This caused the child to go out of scope but the threads were still running. I certainly need to clean up the threads in the destructor.
I am working on a parallel avl tree and have ran into a problem. Here is the function that causes this problem:
template<typename T, int Threads>
bool PTreeSet<T, Threads>::tryInsert(Node* parent, Node* node) {
if (parent->key > node->key) {
return parent->left.compare_exchange_strong(nullptr, node); // <-- Error
} else if (parent->key < node->key) {
return parent->right.compare_exchange_strong(nullptr, node); // <-- Error
} else {
return false;
}
return true;
}
parent->lefthas type atomic<Node*>and I want to set that pointer to node if the current value is null. The compiler complains with error
error: no matching member function for call to 'compare_exchange_strong'
return parent->left.compare_exchange_strong(nullptr, node);
Why is this not valid code?
The first parameter of atomic<T>::compare_exhange_strong is a T&. It requires an lvalue. That's one half of the "exchange": the current value of the atomic is loaded into the object referred to by the first parameter.
You need something like this:
Node* tmp = nullptr;
parent->left.compare_exchange_strong(tmp, node);
As a side effect, if parent->left is not in fact NULL, you get its current value in tmp (which you can ignore if you don't need it, of course).
I'm working on a checker's simulation game for my C++ class. My issue is with the linked list that holds the checkers. I can delete any checker perfectly with the exception of the head of the list. I've looked around here and other websites and I believe there's a memory leak somewhere. I'm fairly new to C++ so I'm not sure what to really do other than playing around with things (which will probably just create a bigger problem). I've never posted here before, so excuse me if the formatting is slightly off or too messy. I'll try to make it brief. First, here's a snippet of the node class for the linked list.
class CheckerpieceNode
{
private:
Checkerpiece *Node;
CheckerpieceNode *Next;
public:
CheckerpieceNode(); // sets Node and Next to NULL in .cpp file
void setNode(Checkerpiece *node);
void setNext(CheckerpieceNode *next);
Checkerpiece* getNode();
CheckerpieceNode* getNext();
};
And the functions are set up pretty much as you would expect in a Checkerpiece.cpp class.
Here's how the code is used. Its called by a Checkerboard object in my main class.
theCheckerboard.removeChecker(theCheckerboard.findChecker(selector->getCurrentX() + 0, selector->getCurrentY() - VERTICAL_SHIFT, listHead), listHead);
The VERTICAL_SHIFT simply has to do with the way my checkerboard graphic is on the console. Since it works perfectly for all other nodes (excluding the head) I've ruled it out as a source of error. Selector is a checkerpiece object but its not part of the list.
Here's the actual findChecker and removeChecker code from Checkerboard class.
Checkerpiece* findChecker(int x, int y, CheckerpieceNode* list_head)
{
if(list_head== NULL) return NULL; // do nothing
else
{
CheckerpieceNode* node = new CheckerpieceNode;
node = list_head;
while(node != NULL && node->getNode() != NULL)
{
if()// comparison check here, but removed for space
{
return node->getNode();
delete node;
node = NULL;
}
else // traversing
node = node->getNext();
}
return NULL;
}
}
void removeChecker(Checkerpiece* d_checker, CheckerpieceNode* list_head)
{
if(list_head== NULL) // throw exception
else
{
CheckerpieceNode *temp = NULL, *previous = NULL;
Checkerpiece* c_checker= new Checkerpiece;
temp = list_head;
while(temp != NULL && temp->getNode() != NULL)
{
c_checker= temp->getNode();
if(d_checker!= c_checker)
{
previous = temp;
temp = temp->getNext();
}
else
{
if(temp != list_head)
{
previous->setNext(temp->getNext());
delete temp;
temp = NULL;
}
else if(temp == list_head) // this is where head should get deleted
{
temp = list_head;
list_head= list_head->getNext();
delete temp;
temp = NULL;
}
return;
}
}
}
}
Oh my, you're complicating it. Lots of redundant checks, assignments and unnecessary variables (like c_checker which leaks memory too).
// Write down the various scenarios you can expect first:
// (a) null inputs
// (b) can't find d_checker
// (c) d_checker is in head
// (d) d_checker is elsewhere in the list
void removeChecker(Checkerpiece* d_checker, CheckerpieceNode* list_head) {
// first sanitize your inputs
if (d_checker == nullptr || list_head == nullptr) // use nullptr instead of NULL. its a keyword literal of type nullptr_t
throw exception;
// You understand that there is a special case for deleting head. Good.
// Just take care of it once and for all so that you don't check every time in the loop.
CheckerpieceNode *curr = list_head;
// take care of deleting head before traversal
if (d_checker == curr->getNode()) {
list_head = list_head->next; // update list head
delete curr; // delete previous head
return; // we're done
}
CheckerpieceNode *prev = curr;
curr = curr->next;
// traverse through the list - keep track of previous
while (curr != nullptr) {
if (d_checker == curr->getNode()) {
prev->next = curr->next;
delete curr;
break; // we're done!
}
prev = curr;
curr = curr->next;
}
}
I hope that helps. Take the time to break down the problem into smaller pieces, figure out the scenarios possible, how you'll handle them and only then start writing code.
Based on this edit by the question author, the solution he used was to:
I modified the code to show the address passing in the checker delete
function.
void delete_checker(Checker* d_checker, CheckerNode* &list_head) // pass by address
{
if(list_head== NULL) // throw exception
else
{
CheckerNode*temp = NULL, *previous = NULL;
Checker* c_checker= new Checker;
temp = list_head;
while(temp != NULL && temp->node!= NULL)
{
c_checker= temp->node;
if(d_checker!= c_checker)
{
previous = temp;
temp = temp->next;
}
else
{
if(temp != list_head)
{
previous->next = temp->next;
delete temp;
temp = NULL;
}
else if(temp == list_head) // this is where head should get deleted
{
temp = list_head;
list_head= list_head->next;
delete temp;
temp = NULL;
}
delete c_checker;
c_checker = nullptr;
return;
}
}
}
}
removeChecker cannot modify the value of list_head as it is past by value. The method signature should be:
void removeChecker(Checkerpiece* d_checker, CheckerpieceNode** list_head)
// You will need to call this function with &list_head
or
void removeChecker(Checkerpiece* d_checker, CheckerpieceNode* &list_head)
// Calling code does not need to change
I have my code as below and I'm getting ConcurrentModificationException, particularly in the line for (String file : files)
I don't change anything for the "file" when doing iteration, so why the exception will be caused and how should I avoid it? Thanks for any suggestion!
int getTotalLength(final HashSet<String> files) {
int total = 0;
int len;
for (String file : files) {
len = getLength(file);
if (len != Long.MIN_VALUE) {
total += len;
}
}
return total;
}
int getLength(String file) {
int len = Long.MIN_VALUE;
if (file == null) {
return len;
}
File f = new File(file);
if (f.exists() && f.isFile()) {
len = f.length();
}
return size;
}
Refering to you comment, declaring final HashSet<String> files makes variable files finale - that means that you cannot assign another object to this variable inside this variable's scope. HashSet itself is mutable object and can be modified - it has nothing to do with final modifier (reference to the set object itselt is still the same).
If you want to work concurently on same object (same hashset) use synchronized blocks or methods.
Generally speaking, you cannot modify collection (in same or another thread) that are beeing iterated with for loop in for-each alike variant.