I'm having a peculiar issue. I thought I knew a decent amount of C++ but I must be overlooking some nuance?
I've got some templated classes, and essentially all that is happening is based on some condition, an object is being moved from one std::list to another.
The method of focus here is the doAndGet( T *t ). My intent is for t to come in as NULL
(or whatever, I really don't care, but it should be NULL
or nullptr
, and if I end up moving a T
element *t
from myList
to myOtherList
, I want T *t
to point to the item that was moved.
Now maybe there is something about std::list
that I'm not aware of, but when stepping through my code, t
gets assigned properly and—originally I thought after the method returned, but later found out that—right before the ret
instruction, argument T *t
gets set back to NULL
Can any guru shed some light on this issue? It's a real head-scratcher for me...
template<typename T, typename C>
class Base : IsDerivedFrom<T, C>
{
public:
typedef std::list<T*> SpecialList;
virtual bool doAndGet( T* t ) = 0;
protected:
SpecialList myList;
};
template<typename T>
class Derived : public Base<T, Other>, public Other
{
public:
Derived( void );
virtual ~Derived( void );
bool doAndGet( T* t );
protected:
typename Base<T, Other>::SpecialList myOtherList;
};
template<typename T>
bool Derived<T>::doAndGet( T *t )
{
// Nothing to process
if (myOtherList.empty()) {return false;}
t = (*myOtherList.begin());
myOtherList.pop_front();
if (true/* some condition needs to be moved */)
{
t->status = 1;
this->myList.push_back(t);
return true;
} else
{
// Something bad happened...
delete t;
t = nullptr;
return false;
}
}
// Use... (pretend I defined MyOtherClass somewhere, not important)
Derived<MyOtherClass> derivedInstance;
MyOtherClass *t = nullptr;
if ( derivedInstance.doAndGet(t) )
{
// ... Here I should expect `t` to be not `NULL` and not `nullptr`
// This however, is not ever the case in my testing...
}
If you want to pass in a variable to a function and have any changes within that function to be reflected back to the caller, you need to use a reference.
C++, like C, is pass by value, where a function only gets a copy of a variable. C++ has references to allow pass by reference.
In other words, your function signature should be:
bool doAndGet( T* &t );
to state that t
is a reference to a T*
, allowing changes to reflect back to the original pointer in the caller.
A simpler example follows:
#include <iostream>
static void change (int a, int &b) { a = b = 0; }
int main() {
int a = 42, b = 42;
change (a, b);
std::cout << a << ' ' << b << '\n';
return 0;
}
This outputs 42 0
because the a
passed in is pass by value and changes are not reflected back to the caller. The b
is passed in as a reference so changes are reflected back.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With