boost variant and memory allocation

Started by
6 comments, last by Zakwayda 15 years, 1 month ago
What is the proper way of dealing with this situation:

boost::variant<int*, myType42> foo;
foo = new int;
delete ...?

That is, what is the proper way of deleting allocated memory held by a variant?
Advertisement
That doesn't seem to be recommended/intended behavior for boost::variant. Perhaps you could use a smart pointer instead of a raw pointer, though.
using direct type check and casting would be something like this.

foo = new int( 123);if( foo.type() == typeid( int *)) {    int *p = boost::get< int *>( foo);    delete p;}

It occurred to me that if all the types that you wish to represent are pod types (pointers int/float etc) and if you handle memory externally, then it might be easier to just use a c-style tagged union. The advantage of boost variant is that it respects constructors/destructors so you can employ normal c++ raii techniques and use it to hold things like std::string or shared_ptr<>. If this is not required or desirable, then a c-style union and an enum will probably achieve the same effect, and with a similar a amount of keyboard jockeying. unions are one the really nice things about c that got lost in c++.
Quote:Original post by _Sigma
What is the proper way of dealing with this situation:
*** Source Snippet Removed ***
That is, what is the proper way of deleting allocated memory held by a variant?


The correct way of deleting pretty much *any* allocated memory is to get someone else to do it for you.

variant<shared_ptr<int>, myType42>
There should NEVER be a delete outside of the destructor of an object that owns a resource.

Learn the basics of C++ programming, particularly RAII and ownership, which are the most important things. Exception-safety is important too (and RAII guarantees the basic guarantee is met).
Quote:
Perhaps you could use a smart pointer instead of a raw pointer, though.
[...]
The correct way of deleting pretty much *any* allocated memory is to get someone else to do it for you.
variant<shared_ptr<int>, myType42>

Thanks. I was going to go this route, but it does involve some code-rewrite, so I just wanted to make sure I wasn't missing something.

Quote:
It occurred to me that if all the types that you wish to represent are pod types (pointers int/float etc) and if you handle memory externally, then it might be easier to just use a c-style tagged union. The advantage of boost variant is that it respects constructors/destructors so you can employ normal c++ raii techniques and use it to hold things like std::string or shared_ptr<>. If this is not required or desirable, then a c-style union and an enum will probably achieve the same effect, and with a similar a amount of keyboard jockeying. unions are one the really nice things about c that got lost in c++.

Sorry, I actually need classes to be held, such as std::string, etc. Thus variant as opposed to a union. I just used int as an example because I was typing this without my contacts in and it was quicker to type int. Sorry!
Quote:Original post by _Sigma
What is the proper way of dealing with this situation:
*** Source Snippet Removed ***
That is, what is the proper way of deleting allocated memory held by a variant?
Although I've never tried it myself, I would assume you would access and/or modify a raw pointer held by a variant in the same way you'd access any other type: via get() or apply_visitor().

Since you're using variant I'm guessing you're already familiar with both of these access methods, but in any case, here's an example using get() (not compiled or tested):

boost::variant<int*, myType42> foo;foo = new int;delete foo.get<int*>();

I'd probably use apply_visitor() myself, but that would have made for a longer example :)

As mentioned previously though, it would probably be better to use an RAII container that can clean up its own resources.

This topic is closed to new replies.

Advertisement