Reverse Iterator not working as expected C++ - c++

Hey i was wondering why this code doesnt give 1 to output.
vector<int> myVector{1, 2, 3, 4, 6};
cout << *myVector.rend() << endl;
Output should be 1 but it gives random numbers.
But in this example everything is okay.
vector<int> myVector{1, 2, 3, 4, 6};
cout << *myVector.rbegin() << endl;
Output : 6
Thanks.

end() points to the memory location after the last element. Similarly, rend() points to memory location before the first element. They are supposed to be used as sentinel values ─ i.e. to iterate until that point is reached.
So, to print 1, you should use:
cout << *(myVector.rend()-1) << endl;

"end" iterators are really "past the end" and not dereferencable, no matter whether they're forward or reverse.
BTW: Enable diagnostic mode for you C++ stdlib. It would have told you something's wrong. How you do that depends on the compiler and stdlib.

In the same way that end() gives an invalid iterator "one item after the range", rend() gives an invalid iterator "one item before the range". So your first example outputs whatever semi-random data happens to be at that place in memory.

Related

unexpected output from C++ multiset lower_bound

Wondeirng why below code returns 1? I never insert 1 into the multiset container.
#include <iostream>
#include <set>
int main ()
{
std::multiset<int> mymultiset;
std::multiset<int>::iterator itlow;
mymultiset.insert(-3);
itlow = mymultiset.lower_bound (3);
std::cout << *itlow << endl; // output 1
return 0;
}
mymultiset.lower_bound(3) returns the lowest location in the container where 3 could go, and that's at the end of the container. So itlow is equal to mymultiset.end(), and it is not dereferenceable. std::cout << *itlow has undefined behavior.
You are trying to get an Iterator which his lower bound is 3, and your maximum value is -3. So you've got an end iterator, which his value is undefined.
You should use multiset::begin() as your Iterator, or put something like itlow = mymultiset.lower_bound (-4); which is not very gentle.
Hi to clarify my understanding
I have one multiset which contains 1 and 5.
mset.insert(1);
mset.insert(5);
auto it = s.lower_bound(6);
cout<<*it<<endl;
Now, from the above answer, I will be getting 2 since that is the location where the value 6 can fit inside the container. Am I right?
Next, if I search for the value 4, I am getting 5.
Here I don't think the iterator has reached the mset.end().
Am I right?
Thanks

Iterator out of range run time exception with an iteration by 2 in a for loop

Here is a piece of my code:
vector<int> v {1, 2, 10, 4, 5, 6, 7, 8, 9 };
for (auto i = v.begin(); i != v.end(); i = i + 2) {
cout << (*i) << " ";
}
What I want to do is to advance the iterator by 2 elements after each iteration. However, there is a runtime exception: offset out of range. So my question is:
Is there a way to iterate by 2 elements each time with a for loop and if possible, can the condition to prevent this exception be defined in the for() statement?
Is there a way to iterate by 2 elements each time with a for loop and
if possible, can the condition to prevent this exception be defined in
the for() statement?
Sure there is a way. The most natural would be this
vector<int> v {1, 2, 10, 4, 5, 6, 7, 8, 9 };
for (size_t i=0; i < v.size(); i = i + 2) {
cout << v[i] << " ";
}
Iterators (just like anything else) arent the best tool for every situation. Iterators are meant to be an abstraction that does not care about an index. Thus when you actually do care about the index, I would not use iterators, but a plain index based loop. Of course its a matter of taste, but being so much used to loops that go from begin to end incremented via ++it, it can help a lot to distinguish a loop that deviates from this usual pattern.
As #tobi303 said, the most suitable way for you is to use indexes and not iterators. Anyway, there's a reason for the Out of Range Exception. If you try with this vector (or in general if you add another element to it):
{1, 2, 10, 4, 5, 6, 7, 8, 9, 1 }
You won't obtain that exception. This is what the doc says about the end method:
Returns an iterator referring to the past-the-end element in the vector container.
The past-the-end element is the theoretical element that would follow the last element in the vector. It does not point to any element, and thus shall not be dereferenced.
So, when *i is equal to 9, and the for loop checks for the end of the vector, it will go on. But if you add 2 to i, the end method will never match the actual end.

How to tell the current 'write position' of a Boost Circular Buffer to enable accessing a previously stored value

I want to access a value in a Boost Circular Buffer that is, for example, 5 positions 'in the past'. So, imagine I am now writing a value '7' to a previous stream of integers:
3, 5, 6, 9, 2, 8, 6
Therefore I have now:
7, 3, 5, 6, 9, 2, 8, 6
I want the '2' since that is 5 positions in the past. How do I get that?
In other words, what is the current 'write index'?
I think that I might need to use boost::circular_buffer<double>::const_iterator but I'm not sure.
I'm not sure I understand correctly, but your worries about modulo indexing seem overly anxious to me. The whole purpose of a circular buffer abstraction is to hide the index arithmetics from the caller, if you ask me.
I'd be thoroughly disappointed in the library design if Boost would let this implementation detail leak out¹
Here's a simple demo that seems to be what you want:
Live On Coliru
#include <iostream>
#include <boost/circular_buffer.hpp>
int main() {
boost::circular_buffer<int> cb(10); // [tag:cb-so-fixedsize] obviously
for (int msg : { 3, 5, 6, 9, 2, 8, 6, 7 }) {
cb.push_back(msg);
}
// should be 2
std::cout << "t0-5: " << cb[4] << "\n";
std::cout << "t0-5: " << *std::next(cb.begin(), 4) << "\n";
// should be 9
std::cout << "t0-5: " << cb[3] << "\n";
std::cout << "t0-5: " << *std::next(cb.begin(), 3) << "\n";
while (!cb.empty()) {
std::cout << cb.front() << " ";
cb.pop_front();
}
}
Prints
t0-5: 2
t0-5: 2
t0-5: 9
t0-5: 9
3 5 6 9 2 8 6 7
¹ I'm well aware that the implementation detail is implied by the name "circular", but hey. Many data structures in the standard library and alike have slightly confusing names
I think the only viable answer is for you to keep track of the index yourself. According to the Boost documentation, it appears that the container has a fixed allocation size and works similar to a stack.
Like other containers, elements do not intrinsically keep track of their key. Therefore, it is up to you to externally keep track of any properties like position or key. It appears that you only have the usual std::vector-like functions available to you: size(), capacity(), at(), operator[], and such, including the iterator functions.
I suppose that the best thing you can do is to find out some way of keeping track of the "keys" or index numbers. Since the circular buffer simply loops around and rewrites over the first array on "overflow," perhaps you could keep a count yourself with a modulo function.

C++ forward iterator arithmetic

Below is a simple program to print the position within a vector of a small range of ints.
int mynumbers [] = { 3, 9, 0, 2, 1, 4, 5 };
vector<int> v (mynumbers, mynumbers + 7);
int m1[] = {9, 0, 2 };
vector<int>::iterator it = find_end (v.begin(), v.end(), m1, m1+3);
if (it != v.end())
cout << "Found at position: " << it-v.begin() << endl;//LINE I
The program as expected prints
Found at position: 1
the find_end function returns a forward iterator.
Logically it makes no sense for me to do so but when I change 'LINE I' to
cout << "Found at position: " << it+v.begin() << endl;//LINE I
I get a compile error.
I know I should be using 'distance' however I am just trying to familiarise myself with the limitations of the various iterator types
Thanks
it is an iterator, it represents a location where an object is.
You say "logically it makes no sense for me to do so..." about it+v.begin(), which is right, because you're adding two locations. What do you get when you add the location of Californa to the location of New York? The question literally makes no sense.
However, you can take the distance between two locations: it-v.begin(). Not sure exactly what you're asking, but I hopefully covered it.
The simple answer is that there is an operation defined for b - a, where b and a are of the same iterator types, but there is no operation defined for b + a.
Sources:
Non-normative: cppreference, RandomAccessIterator
Normative: N4140, [random.access.iterators] Table 111
You're on the right track.
But I think the distance that you mention in your question is your actual solution: http://www.cplusplus.com/reference/iterator/distance/
This is your situation:
begin() --> 3
it --> 9
0
2
1
4
5
distance(v.begin(), it) will tell you how far those two pointers are apart. (In this case 1).
Now keep in mind under the hood distance will just do the same subtraction that you do in this case.
How you should think about it is like this, v.begin() is an address and so is it.
v.begin() is 0x0100
it is 0x0104
when you subtract them you're going to get (0x0104 - 0x0100) / sizeof(int) so you'll get 1.

Segmentation fault trying to dereference an iterator

I'm trying to find the maximum value of a vector using std::max_element. When I run the program I get a segmentation fault that I believe is to do with std::end going over the end of the vector? I've tried changing it to std::end(tempdata)-1) but to no avail.
auto max = std::max_element(std::begin(tempdata), std::end(tempdata));
std::ofstream maxcurrent("maxcurrent.txt", std::ios::app);
maxcurrent << v << std::setw(15) << *max << std::endl;
Having looked at this answer I don't see why mine isn't working.
It won't work when max is std::end(tempdata) which can occurs if your tempdata is empty.
Iterator to the greatest element in the range [first, last). If several elements in the range are equivalent to the greatest element, returns the iterator to the first such element. Returns last if the range is empty.
source