*iterator causes segfault - c++

I'm trying to walk through a list. Here are some declarations:
list<CG1_Edge*> ActiveEdges;
list<CG1_Edge*>::iterator ActiveEdgeIterator;
Sometimes, this code segfaults on line 2:
for (this->ActiveEdgeIterator = this->ActiveEdges.begin(); this->ActiveEdgeIterator != this->ActiveEdges.end(); ++this->ActiveEdgeIterator) {
CG1_Edge* currentEdge = *this->ActiveEdgeIterator;
if (currentEdge->y_up < y)
this->ActiveEdges.erase(this->ActiveEdgeIterator);
}
Are there any common reasons why this might result in a segfault?

You should use something like:
for (this->ActiveEdgeIterator = this->ActiveEdges.begin(); this->ActiveEdgeIterator != this->ActiveEdges.end(); ) {
CG1_Edge* currentEdge = *this->ActiveEdgeIterator;
if (currentEdge->y_up < y)
this->ActiveEdgeIterator = this->ActiveEdges.erase(this->ActiveEdgeIterator);
else
++this->ActiveEdgeIterator;
}
since erase returns an iterator positionned at the next element.
(Note: having that iterator as a member looks strange.)

Begemoth's comment should be the accepted answer. According to the standard erase invalidates "all iterator and references to elements after position"(my mistake; this was for vector and possibly other containers; so at least to avoid surprises you should do well to use the algorithm version instead).
So you'd be safer already using rbegin() and rend(). But why not use the std::alogirthms!
struct Predicate
{
int _y;
explicit Predicate(int y) : _y(y) {}
bool operator()(const CG1_Edge edge) const
{
return currentEdge->y_up < _y;
}
};
std::erase(
std::remove_if(this->ActiveEdges.begin(), this->ActiveEdges.end(), Predicate(y)),
this->ActiveEdges.end());

Related

std::vector Error shows up: "Cannot increment a vector past the end", while wanting to erase specific element

I have a vector of classes, the class has a string name, among other private fields.
I want to implement a void delete(string name) function, which looks for the element based on the string (each class in a vector has a unique name).
However after simple testing, it gives me an error "Cannot increment past the end".
This is my function:
void delete_member(string member_name)
{
int count = 0;
for (auto it = member_list.begin(); it != member_list.end(); ++it, ++count)
if (it->get_name() == member_name)
member_list.erase(member_list.begin() + count);
}
As far as I have searched for an answer, it seems that the iterator shouldn't go past the .end() of the vector.
What is the flaw here? I am using the same loop to iterate over a vector for add_member(Member m) function which works completely fine
The issue is that you erase the element but you do not update the iterators. To avoid dealing with those, it is better to use STL algorithms. The standard usage is as follows
Pre C++20
member.erase(std::remove_if(member.begin(), member.end(), [&](const auto& val)
{
return val.get_name() == member_name;
}), member.end());
In C++20
std::erase_if(member, [&](const auto& val)
{
return val.get_name() == member_name;
});
You are invalidating it when you erase, so later uses of it are undefined, including incrementing and comparing it in the loop test.
You could
for (auto it = member_list.begin(); it != member_list.end(); )
if (it->get_name() == member_name)
it = member_list.erase(it);
else
it++
However there is a standard <algorithm> for this.
auto pred = [&](auto & member){ return member.get_name() == member_name; };
auto new_end = std::remove_if(member_list.begin(), member_list.end(), pred);
member_list.erase(new_end, member_list.end());
In C++20, it will be even easier
auto pred = [&](auto & member){ return member.get_name() == member_name; };
std::erase_if(member_list, pred);

forward_list iterators incompatible

I'm trying to complete a program that evaluates polynomials when given an x-value.
The polynomials are stored using the STL's forward_list in objects of the class.
class PolyTerm {
private:
int _order = 0;
double _coeff = 0.0;
public:
PolyTerm() = default;
PolyTerm(int order, double coefficient) : _order(order), _coeff(coefficient) {}
void setOrder(int order) { _order = order; }
void setCoeff(double coeff) { _coeff = coeff; }
int getOrder() const { return _order; }
double getCoeff() const { return _coeff; }
};
My function which takes the object and the x-value is written as follows:
double evaluate(const forward_list<PolyTerm>& terms, double x) {
double answer = 0;
forward_list<PolyTerm>::iterator it;
while (it != terms.end()) {
answer += it->getCoeff() * pow(x, it->getOrder());
it++;
}
return answer;
}
My compiler doesn't show any errors but once I try to run the program, I get a pop-up saying "Debug Assertion Failed!" with Expression: forward_list iterators incompatible
Image of pop-up
I'm pretty sure I declared the iterator to be of the same type as the list holding the polynomial so I'm not sure why I'm getting this error.
Can anyone explain to me what's wrong?
Thanks in advance for any help.
forward_list<PolyTerm>::iterator it; it's not initialized. It must be initialized with the first element of the forward list.
forward_list<PolyTerm>::iterator it = terms.begin();
You may simplify you loop, and you will not use it
for (const auto& term : terms)
answer += term.getCoeff() * pow(x, term.getOrder());
You also could have used std::accumulate, as that will enforce the initialization using the third argument to the function. Also, since there is no need to declare and initialize iterators, there is no chance you will forget to initialize the iterator.
Here is an example. Note that there are no hand-written loops:
#include <numeric>
//...
double evaluate(const forward_list<PolyTerm>& terms, double x)
{
return std::accumulate(terms.begin(), terms.end(), 0.0, // <-- Note the initial value is 0.0 -- you can't miss it
[&](double total, const PolyTerm& p)
{ return total + p.getCoeff() * pow(x, p.getOrder()); });
}
You never initialize it.
You should have used a for loop.
You should have used a C++11 for(auto it: terms) as I think it would go.

Foreach loops and arrow/dot operator difference?

I have a class Point which has a member method to get position:
class Point {
private:
int x; int y;
public:
Point(int a, int b) {
x = a; y = b;
}
int getX() { return x; }
int getY() { return y; }
};
These are stored in a list<Point> named listPoints. I have a function which checks whether a position matches any of the points in the list:
bool checkMatch(int x, int y) {
for (Point p : listPoints) {
if (p.getX() == x && p.getY() == y) {
return true;
}
}
return false;
}
Note the . is used to access member methods of Point, but there's another way:
bool checkMatch(int x, int y) {
list<Point>::iterator p = listPoints.begin();
for (; p != listPoints.end(); ++p) {
if (p->getX() == x && p->getY() == y) {
return true;
}
}
return false;
}
What is this function doing differently to the one before, specifically why does . no longer work and I need to use -> instead to access member methods of Point? Are these foreach loops fundamentally different?
They're not different no, with some very minor exceptions. In the second loop, you're using an iterator, which is more-or-less a pointer to the object itself. It can be dereferenced to get the actual object.
You'd use iterators if you wanted to remove some elements. So say instead of checking for matches, you were removing anything that matched, you'd want to iterate with iterators.
Since you are just iterating over the entire range, it's far clearer to use your for-ranged loop. It's easier to write and clearer.
specifically why does . no longer work and I need to use -> instead to access member methods of Point?
Because the iterator is an object, which basically points to the actual object. You cannot override the dot operator, so instead operator-> is overridden to retrieve the object. One could also dereference the iterator like *p, which allows you to use the dot operator (*p).getX()
Are these foreach loops fundamentally different?
They are not fundmentally different. They are subtly different.
It's analogous to:
int a;
int* ptr = &a;
a = 10;
*ptr = 10;
The last two lines are not fundmentally different. An iterator is kinda like a pointer. Its operator* is overloaded such that using *p acts as though you are dereferencing a pointer -- you get a reference to an item in the container.
The second block of code can be changed a bit to resemble the first one.
list<Point>::iterator iter = listPoints.begin();
for (; iter != listPoints.end(); ++iter) {
Point& p = *iter;
if (p.getX() == x && p.getY() == y) {
return true;
}
}
Under the covers, the first block is exactly that.
See the documentation on the range-for loop in the standard for the details.

How to use `std::lower_bound` with this custom-made container?

I would like a wrapper for a std::vector<std::vector<T>> object. Here are a few basic methods implemented under Wrapper
template<class T>
class Wrapper
{
private:
std::vector<std::vector<T>>& data;
int totalSize;
std::vector<int> indicesMap;
public:
Wrapper(std::vector<std::vector<T>>& input):data(input)
{
totalSize = 0;
for (int i = 0 ; i < data.size() ; i++)
{
totalSize += data[i].size();
indicesMap.push_back(totalSize);
}
}
T operator[](int index)
{
int whichVector = std::upper_bound(
indicesMap.begin(),
indicesMap.end(),
index
) - indicesMap.begin();
int i = whichVector == 0 ? index : index - indicesMap[whichVector-1];
return data[whichVector][i];
}
int size()
{
return totalSize;
}
};
Here is a simple test
int main()
{
std::vector<std::vector<int>> x;
std::vector<int> x1 = {1,2,3};
std::vector<int> x2 = {10,20,30};
std::vector<int> x3 = {100,200,300};
x.push_back(x1);
x.push_back(x2);
x.push_back(x3);
Wrapper<int> w(x);
std::cout << w[4] << "\n"; // prints 20 as expected
return 0;
}
I would like to be able to use upper_bound and lower_bound on the object Wrapper. I don't really understand how to make iterators to custom-made objects though and fail to implement that and even then, I am not quite sure it is feasible to just give the being and end iterators to lower_bound.
Can you help me to implement upper_bound and lower_bound for the object Wrapper?
My goal would be to be able to do
std::lower_bound(w.begin(), w.end(), object);
You have to create and implement iterators for your wrapper that satisfy concept ForwardIterator. Details on how to do that can be found in answers to this subject How to correctly implement custom iterators and const_iterators?. Then provide methods of your wrapper that return first and behind the past iterator (usually they called begin() and end() and they better be but you can call them whatever way you want).
Iterator can be implemented as std::pair<size_t,size_t> with positions in data plus reference to data itself with proper implementation of operator++.
Optionally for optimization you may want to make your iterator to satisfy RandomAccessIterator concept and std::lower_bound or std::upper_bound could be more efficient (depends on how you implement random access of course).

STL <list> Search List to Find an item property

I don't really have a very good understanding to how STL works.
I was able to create a list and add items to it.
But now I can't seem to search through the list to find an element with a desired property.
Forgive my ignorance on this. I am very new to STL and I still struggle with some elements of C++.
Here is the code. I know it produces errors , but I would like something like this.
Thanks in advance.
extern list<MonsterClass> Monsters;
MonsterClass FindMonster(int x)
{
MonsterClass Monster;
list<MonsterClass>::iterator ListItem;
for(ListItem = Monsters.begin(); ListItem != Monsters.end(); ++ListItem)
{
if (ListItem.X == x)
{
Monster = ListItem;
return Monster;
}
}
return NULL;
}
You are confusing elements and iterators. Iterators are placeholders for positions in the list, they are not the elements themselves. To get to the element, you need to dereference an iterator:
if ((*ListItem).X == x) // or, easier: if(ListItem->X == x)
{
Monster = *ListItem;
return Monster;
}
}
Furthermore, you cannot return NULL since your Monster class cannot take the value NULL (which is a pointer). What you can do is return an iterator instead of the item itself. Then your function does almost exactly the same as the std::find function from the <algorithm> standard header.
// C++03
struct by_X {
by_X( int x ) : x(x) {}
bool operator()( Monster const & m ) const {
return x == m.X;
}
const int x;
};
std::find_if( Monsters.begin(), Monsters.end(), by_X( 5 ) );
If your compiler has lambda (c++0x) support:
std::find_if( Monsters.begin(), Monsters.end(), [=x]( Monster const & m ) { return m.X == x; } );
If you want to do this very often (like, unless it's just for debugging or something like that), a list probably isn't the best choice for the job. Just for one obvious alternative, a std::set directly supports searching like this. In a set the search will normally be quite a bit faster as well (logarithmic instead of linear complexity).