Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
so i have DEBUG_ERROR("vector iterators incompatible"); whenever i have collision detection between blackHole & planet. but when i have collision detection between anything else like asteroid & planet or blackHole & asteroid, then its work with no problem the code is basically the same but yet with this one i have crash
//Blackhole& Planet Collide
for (vector<Entity*>::iterator it = gameEntities.begin(); it < gameEntities.end(); ++it) // This loop usses an iterator (google c++ iterator) to go through all game entites objects
{
BlackHole* blackHole1 = dynamic_cast<BlackHole*> (*it); // As the iterator is of generic type Entity we need to convert it to a type we can use, Ball. Dynamic cast performs the conversion only if the entity is actually a Ball otherwise it gives back a null pointer
if (blackHole1 != nullptr) // we check if the conversion was successful
{
for (vector<Entity*>::iterator it1 = gameEntities.begin(); it1 < gameEntities.end(); ++it1) // and we iterate on the remaining elements in the container
{
if (it != it1)
{
Planet* planet = dynamic_cast<Planet*> (*it1); // we convert the remaining element
if (planet != nullptr) // check if the conversion happended
{
// collision detection: black hole & planet
if (blackHolePlanetCollision(*blackHole1, *planet))
{
blackHole1->increaseMass(blackHole1->getRadius(), planet->getRadius());
delete *it1;
it1 = gameEntities.erase(it1);
//--it1;
any idea what is wrong with it? with any other collision this code works
it1 = gameEntities.erase(it1);
Here you have correctly reset it1 after erasing from the vector (which potentially invalidates existing iterators) … but you did not do the same for it, which is now potentially invalidated.
When it is invalidated and you later try to compare it against the new it1, your standard library implementation has caught the bug and is trying to tell you the comparison is invalid. In a release build I'd expect this to just silently do weird things.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
This post was edited and submitted for review 7 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
for (auto& i : just_a_vec )
Or an iterator for loop.
for (std::vector<std::string>::iterator it = just_a_vec.begin(); it < just_a_vec.end(); it++)
Iterators predate range-based for loops, so they used to be the only of these two alternatives available. Nowadays, range-based for has mostly replaced iterators when dealing with a simple loop.
However, iterators can be used in various other contexts as well. For example, you can do std::sort(v.begin(), std::next(v.begin(), 5)) to sort the first five elements of a vector while leaving the rest of it alone.
Going back to iterating over a whole container:
If you can accomplish what you want with a range-based for, then it leads to more legible code, so they are preferable by default.
If you need iterators for some reason, such as using an algorithm that requires them, or because you need to jump ahead or back while iterating, then use those instead.
Also: In the later case, you can/should still use auto when declaring the iterator:
for(auto it = just_a_vec.begin(); it < just_a_vec.end(); it++) {
}
Edit: as asked: here's a simple, if a bit contrived, example where an iterator-based loop can still be useful:
// adds all values in the vector, but skips over twos values when encountering a 0
// e.g.: {1,2,0,4,5,2} => 5
int my_weird_accum(const std::vector<int>& data) {
int result = 0;
for(auto it = data.begin(); it != data.end(); ++it) {
auto v = *it;
result += v;
if(v == 0) {
// skip over the next two
assert(std::distance(it, data.end()) > 2);
std::advance(it, 2);
}
}
return 0;
}
Quick personal answer: Its somewhat sylistic and based on what version of c++ you are using. I typically prefer range based, but there are certainly moments iterators shine as well. Add both to your toolchest. For further reading.
Here is a list of other SO answers that get more into the performance and use cases.
What's the difference between iterator syntax in range-based loops for STL containers
Is the ranged based for loop beneficial to performance?
range based for loop vs regular iterator for loop
For further information. Google
Range vs iterator loop c++
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am attempting to solve the interview problem from leet code to remove duplicates from a vector of ints.
Below is my my code for the answer:
#include <vector>
#include <set>
using namespace std;
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
vector<int>::iterator itr;
set<int> temp;
for (itr = nums.begin(); itr != nums.end(); itr++) {
if (temp.insert(*itr).second == false) {
nums.erase(itr);
}
}
return nums.size();
}
};
I've added includes for completion.
The problem I've run into is if I have an input vector as so [0,0,1,1,2,2,3,3,4,4,5,5] my function will only erase the duplicates that are not 1 or 2.
Thus my answer will be [0,1,1,2,2,3,4,5]. My understanding is that set will not allow duplicate values but I don't understand why 1 and 2 is still duplicated.
This is because this is undefined behavior.
nums.erase(itr);
std::vector's erase() method invalidates all existing iterators "at or after the point of the erase". Since itr is the "point of the erase", itr is no longer a valid iterator when erase() returns. Subsequent attempt to increment it, in the for loop's iteration results in undefined behavior.
Your C++ textbook will have a more complete explanation of how to use the value that erase() returns, and what it means, in order to correctly avoid undefined behavior; but the capsule summary is:
itr=nums.erase(itr);
Note that now itr points to the value in the vector that's already after what was erase()d, which might be end(); whether it's end() or not you obviously don't want to increment it immediately. It should be obvious that you want to check if the immediately following value in the vector is another duplicate too, don't you agree?
So what you'll need to slightly rework your loop so that it:
Uses erase() correctly
Only increments the iterator if it does not erase() the duplicate value.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am creating function, which takes a vector of operators( different matrices). Operators can be provided in different ordering ( from the smallest to biggest or other way around).
I need to create for loop based on ordering
for(auto tr = operators.begin(); tr != operators.end() ; ++tr )
or
for(auto tr = operators.end(); tr != operators.begin() ; --tr )
content inside of loop stays same
is there any way how to do this automatically? maybe based on some help input parameter?
You can support this by having your function consume a pair of iterators (a "range") instead of a complete matrix or vector. For example:
template <typename Iterator>
void print(Iterator begin, Iterator end) {
for(auto tr = begin; tr != end; ++tr)
; // ...
}
This way, you can pass any sort of range in: forward, reverse, or others. This is how much of the STL is designed.
If you use a std::vector for example, you'd invoke the above like so:
std::vector<int> vec;
print(vec.begin(), vec.end()); // forward
print(vec.rbegin(), vec.rend()); // reverse
Although, technically, an end() iterator can often be decremented and dereferenced safely, you are relying on specific properties that not all iterators are guaranteed to have.
A number of standard containers [some introduced in C++11 do not] have both forward iterators (which iterate through elements in order) and reverse iterators (which iterate over elements in the opposite order). The counterparts of begin() and end() are rbegin() and rend() respectively.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am wondering, how operator == works on list::iterator. I have list of pointers (there are no duplicities) and two iterators which should point to the same place in that list. When I compare directly iterators by == (or !=) I got inequality but when I compare values they are pointing to I got equality. I also tried list.erase on both of then and got the same result.
Example:
list<VirtVertex *> blockList;
void initBlockList(){
/* somehow fill blockList */
for(auto it = blockList.begin(); it != blockList.end(); ++it)
(*it)->BLPosition = it;
}
for(auto it = blockList.begin(); it != blockList.end(); ++it){
if(it == (*it)->BLPosition)
cout << "OK"; //no "OK" printed
if(*it == *((*it)->BLPosition))
cout << "OK"; //got "OK" everytime
}
I am wondering, how operator == works on list::iterator.
operator== on a list::iterator works as you would expect: it returns true if the iterators points to the same element in the same position in the list, or they are both ends.
When I compare directly iterators by == (or !=) I got inequality but when I compare values they are pointing to I got equality.
That's perfectly valid, given that an std::list can contain duplicates.
Two iterators compare equal if they point to the same element of the same container (or to the end). That is as true for all containers, including list.
Comparing values that the iterators point to or reference is not the same as comparing iterators. For a container like list that can contain multiple (duplicate) elements with the same value, two iterators may compare unequal, but the values they reference may be the same. Obviously, if two iterators compare equal, and they are not an end iterator, the values they reference will also compare equal (assuming the element/type has an appropriate comparison operator).
list.erase() invalidates existing iterators of a list, so using previously obtained iterators gives undefined behaviour. However, new iterators subsequently obtained from the list will have the same properties.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
all
I am using vector in C++ STL to store my data. I pass and return them into and from functions. However, as the data size grows, the program is slower and slower. Thus I am updating the codes to an "iterator version".
What I want to archieve is that use iterators to pass, return and iterate STL vectors.
I am now ok with the operations with 1-dimensional vector, just like manipulating the arrays. However, when it comes to 2-dimensional vector, I am a bit confused.
Can anyone show me a simple code example that how to iterate a 2D vector using STL iterator?
Many thanks in advance.
Regards
Long
You state that your basic problem is performance, right?
You assume that this is caused due to copying.
Perhaps there could be simpler solutions for your problem:
Check if vectors can be passed by (const) reference
Check if shared_ptr makes sense
Consider if move semantics can help
Perhaps compiler version or implementation prevent return value optimization
If you need to know the size of a vector, and have two iterators it1 it2,
std::distance(it1, it2);
will tell you the distance between them. This will happen to be the size if they are begin and end
If you have a function like
int work(std::vector<int> items)
{
//...
}
this copies the vector items, so will use more RAM and take longer.
Sending a const ref instead will not copy the vector. Making it const stops you changing it, which might not help you, but you haven't posted any code so I don't know what you want to do.
int work(const std::vector<int> & items)
{
//...
}
Well its already somewhere on stackoverflow
But if you don't want to search here it is :
std::vector<std::vector<int> > vec{ {1,2,3},{4,5,6}};
//Simplest Way:- (C++11)
for(auto row:vec)
{
for(auto col:row)
std::cout<<col<< " ";
std::cout<<std::endl;
}
//OR Using iterator
std::vector<std::vector<int> >::iterator r;
std::vector<int>::iterator c;
for (r = vec.begin(); r != vec.end(); r++) {
for (c = r->begin(); c != r->end(); c++) {
std::cout<<*c<< " ";
}
std::cout<<std::endl;
}
Can get distance only between two iterators of same container
std::vector<int>::iterator s = v2.begin(); //Can be any start
std::vector<int>::iterator e = v2.end(); // Can be any end
std::cout<<"Distance :"<<std::distance(s,e)<<std::endl;