Iterator member behavior
I was expecting the second assert in the following to pass. I'm asking for your help.
Edit: It didn't work when I had poss everywhere instead of poss_a in some places.
#include <vector>
#include <cassert>
class Sampler
{
public:
std::vector<int*> poss;
std::vector<int*>::const_iterator poss_it;
Sa开发者_运维技巧mpler(std::vector<int*> poss_a) : poss(poss_a), poss_it(poss.begin())
{
assert( (poss[0]) == (*poss_it) ); //passes
}
};
int main()
{
int someInt;
std::vector<int*> poss_a(1, &someInt);
Sampler sampler(poss_a);
assert( ((sampler.poss)[0]) == (*(sampler.poss_it)) ); //passes now
return 0;
}
The poss_it(poss.begin())
line in your initializer list is pulling an iterator from the poss that is the input to the constructor, not the one that is a field of the class.
This is a scope issue. When you're in the constructor, it's fine, because your iterator is a pointer to the input to the function. When you leave the constructor however, it's pointing to the same spot in memory but now you have no idea what's at that location.
You should change the name of the input variable in the constructor. You want one that does this:
Sampler(std::vector<int*> input) : poss(input), poss_it(poss.begin())
Whereas what your current one is doing is this:
Sampler(std::vector<int*> input) : poss(input), poss_it(input.begin())
Probably getting confused over the local variables overriding the instance variables, try
#include <vector>
#include <cassert>
class Sampler
{
public:
std::vector<int*> poss;
std::vector<int*>::const_iterator poss_it;
// THIS IS THE LINE I CHANGED
Sampler(std::vector<int*> aPoss) : poss(aPoss), poss_it(poss.begin())
{
assert( (poss[0]) == (*poss_it) ); //passes
}
};
int main()
{
int someInt;
std::vector<int*> poss(1, &someInt);
Sampler sampler(poss);
assert( ((sampler.poss)[0]) == (*(sampler.poss_it)) ); //fails
return 0;
}
You are essentially invoking undefined behavior because sampler.poss_it
is an iterator into a std::vector<int*>
object that was destructed before the second assert
was executed.
The problem was on the line:
Sampler(std::vector<int*> poss) : poss(poss), poss_it(poss.begin())
where the first poss
of poss(poss)
refers to the Sampler
object's poss
member, the second poss
of poss(poss)
refers to the poss
parameter, and the poss
of poss_it(poss.begin())
refers again to the poss
parameter (not the poss
member). The poss
parameter goes out of scope at the end of the constructor, so the poss
parameter is destructed, meaning that the poss_it
iterator is no longer valid.
To avoid this type of problem, C++ programmers almost always avoid shadowing variables. Also, a copy constructor should probably take a const-reference (to avoid pass-by-value for potentially large objects):
Sampler(const std::vector<int*>& poss_) : poss(poss_), poss_it(poss.begin())
精彩评论