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.
Related
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.
this is the first time I've done something like this so I'm a little uncertain how I need to do this. I have a very simple class which contains some simple values and some getters:
class Nucleotide{
private:
char Base;
int Position;
int Polymorphic;
public:
Nucleotide(char ch, int pos);
int getPos();
char getBase();
int getPoly();
};
This class is present in another class that contains a vector of them:
class NucleotideSequence{
private:
std::string Name;
std::vector<Nucleotide> Sequence;
public:
NucleotideSequence(std::string name, std::vector<Nucleotide> seq);
std::string getName();
Nucleotide getBase(int pos1);
};
I want the method of the second class called getBase to be able to take a integer - say 1, and return the first Nucleotide object in the vector. What I've written is below:
Nucleotide NucleotideSequence::getBase(int pos1)
{
for(std::vector<Nucleotide>::iterator i = Sequence.begin(); i != Sequence.end(); i++)
{
if(pos1 == (*i).getPos())
{
return i; // Return a pointer to the correct base.
}
}
}
I've got Nucleotide as the return type but I was wondering really how I should change this - since if I return nucleotide because of pass by value would it not just return a copy of the object at that place in the vector? So I'd rather return a pointer/reference. I'm using an iterator in the loop so should I just return a pointer with the value of the iterator? How do I do this? In the function I return i but should I be returning i&? I'm uncertain about the specifics - presumably if I'm returning a pointer my return type needs to be Nucleotide* or perhaps Nucleotide& since & means address of? I've thought this through and read Cpp tuts but I'm still slightly unsure of the right answer.
Thanks,
Ben.
You have to return the Nucleotide by reference:
Nucleotide & NucleotideSequence::getBase(int pos1)
{
for(std::vector<Nucleotide>::iterator i = Sequence.begin(); i != Sequence.end(); i++)
{
if(pos1 == (*i).getPos())
{
return *i; // Notice the *i instead of i
}
}
}
A reference works very similarly to pointer (allows you to pass the actual object, not its copy), but cannot be null and cannot point to non-existing object, so it's a lot safer than pointer.
Note though, that if you don't find the desired Nucleotide, you don't return anything, what generally is not a good idea. In this case using pointers may actually be a better idea:
Nucleotide * NucleotideSequence::getBase(int pos1)
{
for(std::vector<Nucleotide>::iterator i = Sequence.begin(); i != Sequence.end(); i++)
{
if(pos1 == (*i).getPos())
{
return &(*i);
}
}
return nullptr;
}
You don't return a pointer, you attempt to return the iterator. And the function is declared to return an instance and not a pointer. Also, if you don't find the Nucleotide you don't return anything at all leading to undefined behavior if you try to use the "returned" value.
You could change the function to return a pointer, or a reference, or just a by value (copying like it's declared like not.
You can also change so that the function takes the Nucleotide as an argument instead, and then return a boolean indicator if it was found or not.
bool NucleotideSequence::getBase(int pos1, Nucleotide& n)
{
for (...)
{
if (...)
{
n = *i;
return true;
}
}
return false; // Not found
}
As far as your question is concerned, returning a reference (&) as suggested by others is the solution.
In order to improve your code, I would as well suggest a change:
Either go for the operator[], or use the at() present in std::vector.
Thus, you can directly say:
return Sequence[pos1]; or return Sequence.at(pos1);
Your code will benefit from some use of references for efficiency's sake. The getBase method signature should look like this:
const Nucleotide& NucleotideSequence::getBase(int pos1)
The NucleotideSequence constructor signature should look like this:
NucleotideSequence(const std::string& name, const std::vector<Nucleotide>& seq);
And the getName method like this:
const std::string& getName();
(Although return value optimisation might make that less important.)
As for the contents of getBase, it might help understanding to break down the code into:
const Nucleotide* NucleotideSequence::getBase(int pos1)
{
for(std::vector<Nucleotide>::iterator i = Sequence.begin(); i != Sequence.end(); ++i)
{
Nucleotide& ref = *i; //Get a reference to the object this iterator points to
if(pos1 == ref.getPos()) //compare its base to the argument
{
return &ref; // Return a pointer to the correct object.
}
}
return NULL; //or null if we didn't find the object we wanted
}
I have done numerous searches and found a ton of examples and tutorials but still cannot figure out how to get the value when writing to the [] operator...
I feel like i'm going insane. I must be missing something very simple
as far as i can tell there is a single function for get and set and it looks something like this:
V& operator[](string K);
or this:
double &operator[](int n);
now great, we can get what is:
a[HERE]
as HERE becomes double &operator[](int HERE);
and we can easily work with it
but how do we get what is:
a[4] = HERE
C# has two very clear get and set methods with the value keyword which represents the object being assigned.
public string this[int key]
{
get
{
if(key == 1)
return "1!";
if(key == 2)
return "2!";
else
return "3!";
}
set
{
if( value == "setting") //value is a[3] = THIS
this.isSet = true;
}
}
Don't think of operator[] as a function to get or set, that might be confusing. Think of it as a normal function. In fact, let's re-write it as a normal function:
struct X
{
int arr[10];
int& getIndex(int idx) { return arr[idx]; }
};
//...
//initialize x of type X
x.getIndex(3) = 42;
The method x.getIndex(3) will return a reference to the 4-th element in the member array idx. Because you return by reference, the return value is an l-value and refers to that exact element, so you can assign a value to it, say, 42. This will modify the member x.arr[3] as the function returns an alias for that particular object.
Now you can re-write this in terms of operator[] exactly as before
struct X
{
int arr[10];
int& operator[](int idx) { return arr[idx]; }
};
and get the same result by calling
x[3];
or even
x.operator[](3);
The operator option is just syntactic sugar.
I have the following C++ code:
Some_class * temp1 = findTemp1(...); // returns NULL or a valid pointer
Some_class * temp2 = findTemp2(...); // returns NULL or a valid pointer
Some_class * temp3 = findTemp3(...); // returns NULL or a valid pointer
Now I would like to count how many of these returned a valid pointer (0, 1, 2 or 3).
The only way I can think of is just to test them one by one:
int count = 0;
if (temp1)
count++;
if (temp2)
count++;
if (temp3)
count++;
For 3 pointers, it's not too bad, but it doesn't scale well. Is there a more efficient way assuming I don't redefine the findTempN funcitons (to maybe pass in the counter)?
Thanks a lot for your quick replies! No, I am not going to change the code, I was just wondering what were my other options. I also realized that I cannot be asking for something "scalable" if I am using distinct literals like that to define the 3 pointers. Of course, I didn't think of the things you replied :)
Well, since this is C++ we can go crazy in the quest for terseness... for example:
int count = !!temp1 + !!temp2 + !!temp3;
Update: I probably owe Ivan an explanation of what's going on here.
Assuming temp is any kind of pointer, !temp forces the coercion of the pointer's value to bool (we want to do this) and negates the result (this is a side effect that we do not want). This results in true if the pointer is null and false if the pointer is not null, which is the opposite of what we 'd like. So we add another ! in front to negate the result again.
This leaves us with adding three bool values which coerces them to int and performs the addition, whereupon we have our final result.
You might find it easier to understand the completely equivalent
int count = (bool)temp1 + (bool)temp2 + (bool)temp3;
which I did not use because typing !! is three characters shorter than (bool) (note: you might think that this is a nice trick, but when writing code it is a really bad idea to make decisions based on how many characters you have to type).
The moral of the story is that doing this type of thing can be called either clever or atrocious, depending on who you ask -- but in C++ there has traditionally been high tolerance for atrocities.
Note that if the pointers were in some type of collection to begin with, you could write much better-looking code using std::count_if, e.g.:
bool isNotNull(void* ptr) {
return ptr != 0;
}
std::vector<Some_class*> vec;
vec.push_back(temp1);
vec.push_back(temp2);
vec.push_back(temp3);
int count = std::count_if(vec.begin(), vec.end(), isNotNull);
See it in action.
Or, as very cleverly suggested by MSalters in the comments, you can lose the isNotNull function by counting the pointers which are 0 and subtracting this from the number of all pointers -- but for this, you will need to somehow know what this number is (easy if they are in a vector):
int count = vec.size() - std::count(vec.begin(), vec.end(), 0);
See it in action.
#define N 3
typedef Some_class *PointerGenerator(...);
PointerGenerator funcs[N];
func[0] = &findTemp1;
func[1] = &findTemp2;
func[2] = &findTemp3;
Some_class *ptrs[N];
for(size_t i = 0; i < N; ++i) ptrs[i] = func[i]();
for(size_t i = 0; i < N; ++i) { if(ptrs[i]) ++count; }
C++0x variant:
int count = std::count_if(ptrs, ptrs + N, [](const Some_class *i) -> bool { return i != NULL; } );
The code you have is Good Enough, don't mess with it.
Introducing subtlety is a common novice error, don't do it.
That said, NULL is a valid pointer value, and you can do e.g. count += !!temp1 + !!temp2 + !!temp3 (but that would be newbie obfuscation, do not actually do that).
Cheers & hth.,
If all of the pointers are the same type, put the pointers in a table,
or if you can't do that, make a table of pointers to the pointers. Then
use std::count or std::count_if. Something like:
SomeClass** pointerTable[] =
{
&temp1,
&temp2,
&temp3,
// ...
};
struct IndirectIsNoNull
{
bool operator()( SomeClass** p ) const
{
return *p != NULL;
}
};
// ...
int validPointerCount = std::count_if( begin( pointerTable ),
end( pointerTable ),
IndirectIsNoNull() );
Introduce a static counter.
template<typename T>
struct ValidPointer
{
static unsigned int count;
};
template<typename T>
unsigned int ValidPointer<T>::count = 0;
template<typename T>
static void isValid (const T* const p)
{
if(p)
ValidPointer<T*>::count++;
}
Usage:
isValid(temp1);
isValid(temp2);
...
At any point of time, if you want to retrieve then,
unsigned int count = ValidPointer<Some_class*>::count;
This code can be improved as per your requirement.
Do you need the pointers afterwards? temp suggests otherwise. In that case, you can eliminate those:
int count = 0;
if (findTemp1())
count++;
if (findTemp2())
count++;
if (findTemp3())
count++;
Hide the counter in a class:
class Some_class {};
typedef Some_class* (*FindFunction_t)();
Some_class* findTemp1() {return NULL;}
Some_class* findTemp2() {return new Some_class;}
Some_class* findTemp3() {return new Some_class;}
class Finder
{
public:
Finder() : count_(0) {}
Some_class* CallAndCount(FindFunction_t fn) {return Count(fn());}
int GetCount() const {return count_;}
private:
Some_class* Count(Some_class* p) {if(p) count_++; return p;}
int count_;
};
int main()
{
Finder f;
Some_class* temp1 = f.CallAndCount(findTemp1);
Some_class* temp2 = f.CallAndCount(findTemp2);
Some_class* temp3 = f.CallAndCount(findTemp3);
std::wcout << f.GetCount() << L"\n";
}
The names aren't the best and there are memory leaks but you should get the idea.
I think this meets your objective of scalability although you would need to add template functions if your find functions were to take parameters
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());