|
From: Jim Langston on 21 Feb 2006 01:19 I have a seperate thread function that I was passing a class pointer through a void pointer. Then I realized that the location of my object was changing because it was in a vector like this: std::vector< ThreadConnection > Connections; std::vector< ThreadConnection >::iterator it = Connections.insert( Connections.end(), ThreadConnection() ); And being passed like this: (*it).Handle = reinterpret_cast<HANDLE>( _beginthreadex(0, 0, ClientConnection, static_cast<void*>( &*it ), 0, &(*it).ThreadID) ); The static_cast<void*>( &*it ) is where it's being passed. All well and good, and it works, until another ThreadConnection is inserted into the vector, then the pointer is invalid (took me a little while to figure this one out). So it seems the best solution would be to either pass the pure iterator, which I understand is always supposed to point to the same object, or a reference. But how to do this through a void pointer? The only thing I can think of is something like this: struct ThreadConnWrapper { ThreadConnection& ThreadConnRef; ThreadConnWrapper( ThreadConnection& Ref ): ThreadConnRef( Ref ); }; then creating an instance with: ThreadConnWrapper PassRef( *it1 ); I try this, and after I add a new object to the vector, the reference is invalid. So I try with an iterator (change the above to a std::vector< ThreadConnection >::iterator ) and .. it's invalid as soon as anything is pushed to the vector. So, what can I do other than changing my vector to: std::vector< ThreadConnection* > Connections; then using new and passing the pointer that won't change?
From: James Dennett on 21 Feb 2006 03:30 Jim Langston wrote: > I have a seperate thread function that I was passing a class pointer through > a void pointer. > > Then I realized that the location of my object was changing because it was > in a vector like this: > > std::vector< ThreadConnection > Connections; > std::vector< ThreadConnection >::iterator it = Connections.insert( > Connections.end(), ThreadConnection() ); > > And being passed like this: > > (*it).Handle = reinterpret_cast<HANDLE>( _beginthreadex(0, 0, > ClientConnection, static_cast<void*>( &*it ), 0, &(*it).ThreadID) ); > > The static_cast<void*>( &*it ) is where it's being passed. All well and > good, and it works, until another ThreadConnection is inserted into the > vector, then the pointer is invalid (took me a little while to figure this > one out). > > So it seems the best solution would be to either pass the pure iterator, > which I understand is always supposed to point to the same object That understanding is incorrect; when the item is moved, iterators to it are also invalidated. >, or a > reference. References are also invalidated at the same time as pointers. > But how to do this through a void pointer? The only thing I can > think of is something like this: > > struct ThreadConnWrapper > { > ThreadConnection& ThreadConnRef; > ThreadConnWrapper( ThreadConnection& Ref ): ThreadConnRef( Ref ); > }; > > then creating an instance with: > ThreadConnWrapper PassRef( *it1 ); > > I try this, and after I add a new object to the vector, the reference is > invalid. Yes, that doesn't address the issue at all. > So I try with an iterator (change the above to a std::vector< > ThreadConnection >::iterator ) and .. it's invalid as soon as anything is > pushed to the vector. > > So, what can I do other than changing my vector to: > std::vector< ThreadConnection* > Connections; > then using new and passing the pointer that won't change? You can use a std::list, which doesn't move items, or you can use a std::vector< boost::shared_ptr< ThreadConnection > > if you have access to boost (or std::tr1), or you can pass the items index inside the vector if that's not going to change. std::list is often useful in situations like this precisely because iterators to items tend to be guaranteed to remain valid. -- James
From: Josh Sebastian on 21 Feb 2006 10:10 James Dennett wrote: > Jim Langston wrote: > > I have a seperate thread function that I was passing a class pointer through > > a void pointer. > > > > Then I realized that the location of my object was changing because it was > > in a vector like this: > > > > std::vector< ThreadConnection > Connections; > > std::vector< ThreadConnection >::iterator it = Connections.insert( > > Connections.end(), ThreadConnection() ); > > > > And being passed like this: > > > > (*it).Handle = reinterpret_cast<HANDLE>( _beginthreadex(0, 0, > > ClientConnection, static_cast<void*>( &*it ), 0, &(*it).ThreadID) ); > > > > The static_cast<void*>( &*it ) is where it's being passed. All well and > > good, and it works, until another ThreadConnection is inserted into the > > vector, then the pointer is invalid (took me a little while to figure this > > one out). > > You can use a std::list, which doesn't move items That was my first thought, too. > or you can pass > the items index inside the vector if that's not going to > change. Just to add some meat to that: template<typename T> class vector_elm_ref { public: vector_elm_ref(std::vector<T>& vec, std::vector<T>::size_type idx) : vec_(vec), idx_(idx) { } T& operator*() { return vec[idx]; } private: std::vector<T>& vec; std::vector<T>::size_type idx; }; > > std::vector< ThreadConnection > Connections; > > std::vector< ThreadConnection >::iterator it = Connections.insert( > > Connections.end(), ThreadConnection() ); vector_elm_ref<ThreadConnection>* ptc_ref = new vector_elm_ref<ThreadConnection>(Connections, it - connections.begin()); (**ptc_ref).Handle = reinterpret_cast<HANDLE>( _beginthreadex( 0, 0, ClientConnection, ptc_ref, 0, &((**ptc_ref).ThreadID) ) ); Josh
From: Jim Langston on 21 Feb 2006 20:28 "James Dennett" <jdennett(a)cox.net> wrote in message news:JcAKf.34$p43.0(a)fed1read05... > Jim Langston wrote: >> I have a seperate thread function that I was passing a class pointer >> through a void pointer. >> >> Then I realized that the location of my object was changing because it >> was in a vector like this: >> >> std::vector< ThreadConnection > Connections; >> std::vector< ThreadConnection >::iterator it = Connections.insert( >> Connections.end(), ThreadConnection() ); >> >> And being passed like this: >> >> (*it).Handle = reinterpret_cast<HANDLE>( _beginthreadex(0, 0, >> ClientConnection, static_cast<void*>( &*it ), 0, &(*it).ThreadID) ); >> >> The static_cast<void*>( &*it ) is where it's being passed. All well and >> good, and it works, until another ThreadConnection is inserted into the >> vector, then the pointer is invalid (took me a little while to figure >> this one out). >> >> So it seems the best solution would be to either pass the pure iterator, >> which I understand is always supposed to point to the same object > > That understanding is incorrect; when the item is moved, > iterators to it are also invalidated. > >>, or a reference. > > References are also invalidated at the same time as pointers. > >> But how to do this through a void pointer? The only thing I can think of >> is something like this: >> >> struct ThreadConnWrapper >> { >> ThreadConnection& ThreadConnRef; >> ThreadConnWrapper( ThreadConnection& Ref ): ThreadConnRef( Ref ); >> }; >> >> then creating an instance with: >> ThreadConnWrapper PassRef( *it1 ); >> >> I try this, and after I add a new object to the vector, the reference is >> invalid. > > Yes, that doesn't address the issue at all. > >> So I try with an iterator (change the above to a std::vector< >> ThreadConnection >::iterator ) and .. it's invalid as soon as anything is >> pushed to the vector. >> >> So, what can I do other than changing my vector to: >> std::vector< ThreadConnection* > Connections; >> then using new and passing the pointer that won't change? > > You can use a std::list, which doesn't move items, or you > can use a std::vector< boost::shared_ptr< ThreadConnection > > > if you have access to boost (or std::tr1), or you can pass > the items index inside the vector if that's not going to > change. std::list is often useful in situations like this > precisely because iterators to items tend to be guaranteed > to remain valid. Thanks, changed it to std::list and wound up not having to change any code at all. Passing iterator to the object in the list and all is well.
|
Pages: 1 Prev: Help with input/output files Next: What is equivalent to NULL? Why not EOF? |