Why does it seem like the set is not one-to-one copied when passed as an argument? I suppose it has something to do with the fact that the iterator points at the original set whereas a new copied set is created. So the s.end() would point to the end pointer of the copied set and not the original set. But I don't understand the non terminating output below.
Why does this give an output of "-812375757575757575...":
#include <iostream>
#include <set>
void f (std::set<int>::iterator itr, std::set<int> s)
{
if (itr != s.end())
{
std::cout << *itr;
itr;
f(itr, s);
}
}
int main()
{
std::set<int> s {1, 2, 3, 7, -8};
f(s.begin(), s);
return 0;
}
Whereas this gives an output of "-81237":
#include <iostream>
#include <set>
void f (std::set<int>::iterator itr, std::set<int>& s)
{
if (itr != s.end())
{
std::cout << *itr;
itr;
f(itr, s);
}
}
int main()
{
std::set<int> s {1, 2, 3, 7, -8};
f(s.begin(), s);
return 0;
}
CodePudding user response:
The first code exhibits undefined behavior, hence the erroneous output.
On each call to f()
, the s
parameter is being passed in by value, which means a copy of the caller's set
object is being made. As such, you end up comparing iterators that don't belong to the same set
object, which is undefined behavior. In your case, your loop does not end when you expect it to, causing the iterator to eventually go beyond the bounds of the original set
object into memory that doesn't belong to the original set
. That is where the erroneous output values are coming from.
The second code fixes that issue by passing the s
parameter by reference instead, so no copies are ever made, and thus iterators that belong to the same set
object are compared, and the loop ends when expected. No undefined behavior.