Dereferencing iterator behavior in C++ - c++

I'm trying to figure out why dereferencing the empty list iterator is preventing the rest of the code from running. Comment out the line and everything seems fine, but leave it in and the program doesn't seem to get past that point.
I guess it's supposed to be an error since the list is empty, but I'm not getting any warnings or errors.
I'm using codeblocks with MinGW
std::list<std::string> slist;
std::string word;
auto iter = slist.begin();
//what is this doing?
std::cout << (*iter) << std::endl;
while(std::cin >> word)
{
iter = slist.insert(iter, word);
}
slist.insert(slist.begin(), {"foo", "bar"});
for(auto item: slist)
std::cout << item << std::endl;

Well std::list is empty! De-referencing means you are attempting to use something that is not defined. It is just wrong. You should definitely not do that.
You should do instead
for (auto i : slist)
std::cout << i << std::endl;
which is safe.

Related

About iterator of containers

I do not know, why does it output 1024?
vector<int> default_container = { 1,2,3,4,5,6,7,78,8,1024 };
cout << *default_container.end() << endl; // 0
default_container.pop_back();
for (auto it : default_container)
{
cout << it << ",";
}
cout << endl;
cout << *default_container.end() << endl; // 1024 why?why?why?why?
cout << *--default_container.end() << endl; // 8
Your program has Undefined behavior!
You are de-referencing the end iterator, at the lines
cout << *default_container.end() << endl;
...
cout << *default_container.end() << endl;
which gives you undefined behavior. Form cppreference.com the std::vector::end, std::vector::cend
Returns an iterator to the element following the last element of the vector.
This element acts as a placeholder; attempting to access it results in undefined behavior.
Means, anything can be happened; therefore you shouldn't be relaying on its result and should not be doing it!
That being said, it looks like that you want to access the last element in the vector. If that the case, for a non-empty vector you have multiple other (safe) choices:
Using std::vector::back
// prints first 8 from last; due to "default_container.pop_back()"
std::cout << default_container.back();
Using std::prev
#include <iterator>
// prints first 8 from last; due to "default_container.pop_back()"
std::cout << *std::prev(default_container.end());
Using reverse iterator std::rbegin
// prints first 8 from last; due to "default_container.pop_back()"
std::cout << *std::rbegin(default_container);
As a side note, see: Why is "using namespace std;" considered bad practice?
The previous answer says it all.
In other words you're not supposed to use end() for anything else then comparing an iterator to.
Eg.
for (auto it = container.begin(); it < container.end(); ++it)
Also note that your line for (auto it : default_container)
isn't creating an iterator but literally an int.
// foreach value in container
for(int value : default_container)
{
cout << value;
}
note that if you're not planning to change the values you're iterating over you can use this :
for(const auto value : default_container) {}
or if your containter contains objects (instance of classes)
for(const auto& object : container) {}

C++ First two elements not printing properly when using iterator

I have looked for this and found something here: Variable not printing on iteration but I'm not sure if that necessarily applies.
What I have going on is my program correctly prints all values when I call it like this:
for (int i = 0; i < SampleVec.Matchups().size(); ++i){
std::cout << SampleVec.Matchups()[i] << std::endl;
}
or when I call it like this:
std::vector<int> temp;
temp = SampleVec.Matchups();
for (std::vector<int>::const_iterator iter = temp.begin(); iter != temp.end(); iter++){
std::cout << *iter << std::endl;
}
but when I write it like this
for (std::vector<int>::const_iterator iter = SampleVec.Matchups().begin(); iter != SampleVec.Matchups().end(); iter++){
std::cout << *iter << std::endl;
}
the first two values show up as a 0 and the rest print correctly. In the link I posted they talk about stripping newlines from the input, but I don't know if that applies here or even how to do that. I can post full code if needed to run and see the functionality in action.
for (std::vector<int>::const_iterator iter = SampleVec.Matchups().begin(); iter != SampleVec.Matchups().end(); iter++){
std::cout << *iter << std::endl;
}
begin() returns the iterator of the beginning of a temporary std::vector returned by Matchups(). At the moment of using iter it's a dangling iterator because the temporary has been destroyed and thus you have Undefined Behaviour.
You have to store the result before trying to access it through an iterator like you do in example 2.

C++ How to print a string backwards?

I'm trying to print an std::string backwards with iterators like this:
std::string back = "hello";
for(std::string::iterator it=back.end(); it!=back.begin(); --it)
{
std::cout << (*it);
}
But the output will only print out:
olle
Why is it not also printing out the h? I tried a couple of different things and played around with it, but I just can't seem to figure out why. Any help would be greatly appreciated, thanks!! :)
std::string back = "hello";
for (std::string::reverse_iterator it = back.rbegin(); it != back.rend(); ++it)
{
std::cout << (*it);
}
std::string::iterator it=back.end();
it gets initialized to end(). Then, inside of the loop:
std::cout << (*it);
Since the initial value of it is end(), dereferencing it is undefined behavior, with unpredictable results.
The correct approach is to decrement it before it gets dereferenced:
for(std::string::iterator it=back.end(); it!=back.begin(); )
{
--it;
std::cout << (*it);
}
If you don't want a for-loop:
#include <algorithm>
std::string string_back = "hello";
std::reverse(string_back.begin(), string_back.end());
std::cout << string_back; // prints 'olleh'

remove duplicates entry in vectors

I am trying to add objects using class(Sample),sort my vector and after that remove duplicates entries in my vector.
my codes (this is just part of my codes in my program)
vector<Sample> sampleVector;
sort(sampleVector.begin(), sampleVector.end());
sampleVector.erase(std::unique(sampleVector.begin(),sampleVector.end(),sampleVector.end()));
but however it when I tried to run my program it shows this error.
Type 'std::__1::__wrap_iter<Sample *>' does not provide a call operator
and I realized that most likely the error is caused by this line
sampleVector.erase(std::unique(sampleVector.begin(),sampleVector.end(),sampleVector.end()));
What should I do so that I can make it work to remove duplicate entries in my vector?
thanks in advance
Another thing I have tried but it's not working.
bool myfunction (Sample *i,Sample *j) {
return (i==j);
}
std::vector<Sample>::iterator it;
vector<Sample> sampleVector;
it = std::unique(sampleVector.begin(), sampleVector.end(),myfunction);
for (it=sampleVector.begin(); it!=sampleVector.end(); ++it) {
std::cout << *it << " "; <-- error must change it to &*it
}
Misplaced parenthesis. Correction:
sampleVector.erase( std::unique(sampleVector.begin(),sampleVector.end()),
sampleVector.end() );
I don't blame you for getting caught out. C++ compiler errors are heinous.
I think you can try this code below
bool myfunction (int i, int j) {
return (i==j);
}
std::unique (myvector.begin(), myvector.end(), myfunction);
std::cout << "myvector contains:";
for (it=myvector.begin(); it!=myvector.end(); ++it){
std::cout << ' ' << *it;
}
std::cout << '\n';
Hope it will help!
Another possibility worth considering is that you could put the sorted elements into an std::set. That will retain the sorted ordering and ensure item uniqueness.

Differences between std::set and boost::ptr_set?

I've changed some code to convert a std::set to a boost::ptr_set. However, the code doesn't compile; the problem is that I'm assuming that the return value from a ptr_set insert is the same as a set insert (a pair<myIter, bool>). After an hour on Google I found this, and it turns out that the return value from a ptr_set insert appears to be a bool.
Is there any definitive documentation on the differences between the ptr containers and the std containers? I haven't found anything on the boost website, but maybe I'm just being dumb...
EDIT
Ok - what was confusing me was that this code
t.insert(s.release(s.begin()));
p = t.insert(s.release(s.begin()));
reports no error on the first line on gcc, but reports no match for operator= on the second line, so I thought the error was in the return type. However, if you comment out the second line, the first line is then reported as an error (release doesn't return an iterator). My confusion was compounded by the link I posted, in which ptr_container's author states that "insert() in ptr_set<> returns bool". However, reading on down the link it becomes obvious that the code hadn't been finished at the time. Thanks Kerrek.
The following code works as expected, and the interface is the same as for std::set::insert():
#include <boost/ptr_container/ptr_set.hpp>
#include <boost/assign/ptr_list_inserter.hpp>
#include <iostream>
int main()
{
boost::ptr_set<int> s;
{
auto p = s.insert(new int(4));
std::cout << "Element " << *p.first << (p.second ? " inserted" : " already existed") << std::endl;
}
{
auto p = s.insert(new int(4));
std::cout << "Element " << *p.first << (p.second ? " inserted" : " already existed") << std::endl;
}
boost::assign::ptr_insert(s)(1)(2)(3)(4);
for (auto it = s.begin(), end = s.end(); it != end; ++it) { std::cout << *it << "\n"; }
}
The documentation is perhaps not the easiest to navigate, but it's all there. You should look for the "set adapter", though, perhaps that's not entirely obvious.