Jump to content
  • Advertisement
Sign in to follow this  

Quick question about for

This topic is 4772 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was wondering, if I use a function to retreive a value for the for function, will it be retreieved every loop, or is it just retreived at the beggining?
for(int x; x < Variable.GetValue(); x++)
Basically, I want to go through a vector and do some stuff to its variables, and if it returns 1, the specific element would be deleted. In this scenario, the size of the vector should decrease and the loop should be done one less time. Hence, that's why the retreived value needs to be updated every loop.
//Vector is a vector of pointers
 for(int x = 0; x < Vector.size(); x++)
   if(Vector[x]->Animate(Time)) //if returns 1, delete it
      {
       delete Vector[x];
       Vector.erase(Vector.begin()+x);
      }


I've actually gone and tested it out and it doesn't get me any errors, so I think I'm fine. Thanks!

Share this post


Link to post
Share on other sites
Advertisement
its evaluated every iteration. just fyi:

for( initializations; conditions; loop operation )
{...}

In the 'for' construct, only initialization occurs ONCE. All others occur for each iteration. So watever u put in condition will be evaluated each round irrespective if its a function or variable. Hope that helps.

Share this post


Link to post
Share on other sites
I could be wrong, but I'm not sure if that'll erase the whole vector if they all return 1. Problem is that x is increasing while the vector is decreasing:

Vector: { 0, 1, 2, 3, 4, 5 }

X = 0 so we delete Vector[0]

Vector: { 1, 2, 3, 4, 5 }

X = 1 so we delete Vector[1]

Vector: { 1, 3, 4, 5 }

X= 3 so we delete Vector[2]

Vector: { 1, 3, 5 }

X = 4 which is bigger than the Vector's size.

Can you see what I mean?

Things will really get messy anytime there are two deletions needed in a row since the next one will take the previous one's place, while the index will still be incremented.

If I'm making any sense (again, I could be wrong), you should be able to decrement x anytime you delete something and be fine.






Share this post


Link to post
Share on other sites
std::vector<whatever*>::iterator itor = Vector.begin();

while(itor != Vector.end())
{
if((*itor)->Animate(Time))
{
delete *itor;
itor = Vector.erase(itor);
}
else ++itor;
}


Or even


#include <functional>
#include <algorithm>

struct AnimateAndDeleteIfDead :
std::unary_function<whatever*, bool>
{
some_time_type t_;

AnimateAndDeleteIfDead(some_time_type t) : t_(t) {}

bool operator()(whatever* ptr)
{
bool dead = ptr->Animate(t);
if(dead) delete ptr;
return dead;
}
};

...

std::vector<whatever*>::iterator garbage;
garbage = std::remove_if( Vector.begin(), Vector.end(),
AnimateAndDeleteIfDead(Time) );
Vector.erase(garbage, Vector.end());

Share this post


Link to post
Share on other sites
Or, if you're really into generic code


#include <cstdlib>
#include <functional>
#include <algorithm>
#include <iostream>
#include <vector>

template<class Itor, class Pred, class Func>
Itor remove_if_cleanup( Itor first, Itor last, Pred pred, Func cleanup)
{
Itor write = first;
while(first != last)
{
if( pred(*first) )
{
cleanup(*first);
*write = *first;
++write;
}

++first;
}

return write;
}

template<class T>
struct delete_ptr :
std::unary_function<T*, void>
{
void operator()(T* ptr) const { delete ptr; }
};

struct whatever
{
bool Animate(int time) { return time % 2; }
~whatever() { std::cout << "deleted" << std::endl; }
};

int main()
{
std::vector<whatever*> vec;
for(int i = 0; i < 30; ++i) vec.push_back(new whatever);

int time = 1;

std::vector<whatever*>::iterator garbage;
garbage = remove_if_cleanup( vec.begin(), vec.end(),
std::bind2nd
(
std::mem_fun(&whatever::Animate),
time
),
delete_ptr<whatever>()
);

vec.erase( garbage, vec.end() );
}




Or you can take a leaf from std::bind2nd and write your own functor combiner


#include <cstdlib>
#include <functional>
#include <algorithm>
#include <iostream>
#include <vector>

template<class Pred, class Func>
struct caller_if :
std::unary_function< typename Pred::argument_type,
typename Pred::result_type >
{
Pred pred_;
Func func_;

caller_if( Pred pred, Func func ) :
pred_(pred),
func_(func)
{}


typename Pred::result_type operator()( typename Pred::argument_type arg )
{
bool test = pred_(arg);
if(test) func_(arg);
return test;
}
};

template<class Pred, class Func>
caller_if<Pred,Func> call_if( Pred pred, Func func )
{
return caller_if<Pred,Func>(pred, func);
}

template<class T>
struct delete_ptr :
std::unary_function<T*, void>
{
void operator()(T* ptr) const { delete ptr; }
};

struct whatever
{
bool Animate(int time) { return time % 2; }
~whatever() { std::cout << "deleted" << std::endl; }
};

int main()
{
std::vector<whatever*> vec;
for(int i = 0; i < 30; ++i) vec.push_back(new whatever);

int time = 1;

std::vector<whatever*>::iterator garbage;
garbage = remove_if( vec.begin(), vec.end(),
call_if
(
std::bind2nd
(
std::mem_fun(&whatever::Animate),
time
),
delete_ptr<whatever>()
)
);

vec.erase( garbage, vec.end() );
}




Or you may pull in the Boost Lambda library

#include <algorithm>
#include <iostream>
#include <vector>

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/if.hpp>
#include <boost/lambda/construct.hpp>

using namespace boost::lambda;

struct whatever
{
bool Animate(int time) { return time % 2; }
~whatever() { std::cout << "deleted" << std::endl; }
};

int main()
{
std::vector<whatever*> vec;
for(int i = 0; i < 30; ++i) vec.push_back(new whatever);

int time = 1;

bool dead;
std::vector<whatever*>::iterator garbage;
garbage = remove_if( vec.begin(), vec.end(),
(
var(dead) = bind( &whatever::Animate, _1, time ),
if_( dead )
[
bind(delete_ptr(),_1)
],
dead
)
);

vec.erase( garbage, vec.end() );
}




At which point you might decide to just kill me, because if you had just used a container of smart pointers, no manual deletion would have been needed:


GNU nano 1.3.4 File: foo.cc

#include <algorithm>
#include <iostream>
#include <vector>

#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>

using namespace boost;

struct whatever
{
bool Animate(int time) { return time % 2; }
~whatever() { std::cout << "deleted" << std::endl; }
};

int main()
{
typedef shared_ptr<whatever> sp_whatever;

std::vector<sp_whatever> vec;
for(int i = 0; i < 30; ++i) vec.push_back( sp_whatever(new whatever));

int time = 1;

std::vector<sp_whatever>::iterator garbage;
garbage = remove_if( vec.begin(), vec.end(), bind( &whatever::Animate, _1, time ) );
vec.erase( garbage, vec.end() );
}



Have fun.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!