A struct for putting in parameters passed around in a set of functions
I need the flexibility of being able to change parameters passed around to different functions, depending from where the call to the function happened, so I decided I'd put all my parameters in a struct, however most of these parameters are structs or classes themselves and I want to have the option of leaving them NULL, so I have to pass pointers to the structs/classes.
struct A
{
otherB* b; // NULL should be a valid value
otherC* c;
};
However my question is now, passing A around these pointers will be the only thing copied, so if I did the following there would be a problem right?
void func(A& a) //non co开发者_如何学Pythonnst cause I wanna change contents of A.
{
a.b = new b();
}
A myA;
otherC somec; // all these are currently automatic variables in my pgm.
myA.c = &somec;
func(myA); //myA goes out of scope? so I've lost all pointers assigned and since somec is out of scope too, I have a problem?
What would the best way to resolve something like this+ I want the flexibility of being able to pass NULL to any of my parameters, however not sure if using raw pointers everywhere is a good idea?
To solve the problem of resource management, you should use boost::shared_ptr
(or std::shared_ptr
in C++0x).
struct A
{
boost::shared_ptr< otherB > b;
boost::shared_ptr< otherC > c;
};
void func(A& a)
{
a.b = boost::make_shared< otherB >();
}
A myA;
otherC somec;
myA.c = boost::shared_ptr< otherC >(&somec, null_deleter());
func(myA);
When myA
goes out of scope, all resources are deallocated automatically. Since somec
was allocated on the stack, we wrapped it in a shared_ptr
that uses a null_deleter
, that could look like this:
struct null_deleter {
void operator()(void *) { }
};
This will not delete the object, it will do nothing (which is just what we want for stack-allocated objects). Keep in mind however, that you have to make sure that somec
lives longer than myA
, otherwise you will get access violations.
boost::optional<>
Allows you to test if the field is set or not.
Simple example (will not compile, I've not even remotely tested it, in theory this is how it should work)
struct params
{
boost::optional<int> a;
boost::optional<foo> b;
boost::optional<bar> c;
};
void func(params& p)
{
if (p.a)
{
// do stuff with a
}
if (p.b)
{
// do stuff with b
}
if (p.c)
{
// do stuff with c
}
else
p.c = bar(); // again copy constructed and now initialized...
}
params p;
p.a = 1;
p.b = foo(); // copy constructed, however you can store a reference in the optional too.
// c is uninitialized
func(p);
// when p goes out of scope, everything is gone..
You basically have to analyze ownership, i.e. who can allocate and who is responsible for deleting object once they no longer is used.
One thing that is important to remember is that if you mix dynamically allocated things and things placed on the stack, you simply can't apply delete
on them, as it's not possible to delete things on the stack.
One way could be to only use new
and define a destructor in A
that deletes all it's pointers. Another way could be a place where you would register objects that later should be deleted. Or you could go the route of using existing reference-counting tools, as suggested in other answers.
No, your idea of the scope of myA
and somec
are wrong. There's nothing wrong with what you have right now- although I personally think that references would be a superior option to pointers.
void func(A& a) //non const cause I wanna change contents of A.
{
a.b = new b();
}
int main() {
A myA;
otherC somec; // all these are currently automatic variables in my pgm.
myA.c = &somec;
func(myA);
// myA and somec are still perfectly in scope to be saved, or deleted, or w/e as you like
}
It's not clear from your description, but if you're having a problem because somec is going out of scope, it can only be because func is saving a copy of the pointer. Don't do that: in funct, copy the object, not the pointer.
PS: if most of the pointers are null most of the time, you should consider using something like following syntactic sugar:
struct A
{
// pointer members...
A() : // ... set all pointers to null...
A& withB( B const& someB ) { otherB = &someB; return *this ; }
A& withC( C const& someC ) { otherC = &someC; return *this ; }
// And so on for all of the rest of the pointers.
};
func( A().withC( somec ) );
Don't know if it's appropriate for your situation, but it's often convenient.
精彩评论