Reputation: 57
The situation is a little complicated, but I'm going to try to explain it as best as I can.
I'm trying to get a pointer to an object from a vector of object pointers where one of the object's attributes matches a variable string. To do this, I'm binding the string variable to a function and then using the bound function to try and find that object pointer. However, it keeps crashing whenever I try this. I've tried a bunch of different tests to find the problem, but I'm still clueless. Here's the relevant code:
class A {
std::string n;
...
public:
const std::string getN() {
return n
}
};
static bool checkN(std::string n1, A* a) {
if (a->getN() == n1) {
return true;
}
else {
return false;
}
}
void function() {
using namespace std::placeholders;
A* a;
std::string compare = "Yes";
const std::vector<A*> As; //As[0].n = "Yes";
auto check = std::bind(checkN, compare, _1);
a = (*std::find_if(As.begin(), As.end() - 1, check)); //This is the line where it crashes.
}
Note that this is something of a simplified version, but I think it gets the point across. Any suggestions? Edit: Made some syntax errors in trying to simplify the code. Fixed them.
Upvotes: 1
Views: 659
Reputation: 3956
As
is a const std::vector<A*>
that contains no elements inside it, so dereferencing the iterator returned by std::find_if(...)
in this case is Undefined Behavior.
Since you don't mention anything about why you do As.end() - 1
in std::find_if(...)
, I will assume that you did so in an attempt to get rid of the segmentation fault, but I am afraid that won't get rid of the above problem either.
Now, coming to what you do need to prevent this sort of Undefined Behavior from occurring is to check whether the iterator returned by std::find_if(...)
is not past the last element of the container (i.e., check whether std::find_if(...) != As.end()
and only then should you try to dereference the iterator returned by std::find_if(...)
.
#include <functional>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <iomanip>
#include <vector>
#include <string>
// ...
int main() {
using namespace std::placeholders;
std::string compare = "Yes";
const std::vector<A*> As;
// Store the iterator returned by 'std::find_if(...)' inside a variable
auto it = std::find_if(As.begin(), As.end(), std::bind(checkN, compare, _1));
// Check whether the iterator is NOT past the last element i.e. check if it is not equals 'As.end()'
if (it != As.end())
std::cout << std::quoted(compare) << " found at index " << std::distance(As.begin(), it) << "!" << std::endl;
// Otherwise, if the iterator is, in fact, equals 'As.end()', then it is safe to assume that the element was not found
else
std::cout << std::quoted(compare) << " was not found." << std::endl;
}
Upvotes: 4