Jump to content
  • Advertisement
Sign in to follow this  
MARS_999

new in C++ and no call to delete?

This topic is 2609 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 am looking at using this code to a replacement for boost's optional class. Problem is I don't understand how this will not leak since I see no call to delete? I see a destructor called....


class OptionalEmpty{};

template<unsigned long size>
class OptionalBase
{
protected:
bool valid;
char data[size];

public:
OptionalBase() : valid(false){}
OptionalBase& operator=(OptionalBase const& rhs)
{
valid = rhs.valid;
return *this;
}
OptionalBase(OptionalBase const& rhs) : valid(rhs.valid){}
virtual ~OptionalBase(){}
bool const Valid(void) const
{
return valid;
}
bool const InValid(void) const
{
return !valid;
}
};

template<class T>
class Optional : public OptionalBase<sizeof(T)>
{
private:
T const* const Get(void) const
{
return reinterpret_cast<T const* const>(data);
}
T* const Get(void)
{
return reinterpret_cast<T* const>(data);
}
void Construct(T const& t)
{
new (Get()) T(t);
}
void Destroy(void)
{
Get()->~T();
}

public:
Optional(){}
Optional(T const& rhs)
{
Construct(rhs);
valid = true;
}
Optional(OptionalEmpty const& rhs){}
Optional& operator=(T const& rhs)
{
if(valid)
{
*Get() = rhs;
}
else
{
Construct(rhs);
valid = true;
}
return *this;
}
Optional(Optional const& rhs)
{
if(rhs.valid)
{
Construct(*rhs);
valid = true;
}
}
virtual ~Optional()
{
if(valid)
Destroy();
}
Optional& operator=(Optional const& rhs)
{
assert(!(this == &rhs)); // don't copy over self!
if(valid)
{ // first, have to destroy our original.
valid = false; // for exception safety if destroy() throws.
Destroy();// (big trouble if destroy() throws, though)
}
if(rhs.valid)
{
Construct(*rhs);
valid = true;
}
return *this;
}
bool const operator==(Optional const& rhs) const
{
if((!Valid()) && (!rhs.Valid()))
{
return true;
}
if(Valid() ^ other.Valid())
{
return false;
}
return ((* *this) == (*rhs));
}
bool const operator<(Optional const& rhs) const
{
// equally invalid - not smaller.
if((!Valid()) && (!rhs.Valid()))
{
return false;
}
// I'm not valid, other must be, smaller.
if(!Valid())
{
return true;
}
// I'm valid, other is not valid, I'm larger
if(!rhs.Valid())
{
return false;
}
return ((* *this) < (*rhs));
}
T const& operator*(void) const {assert(valid); return *Get();}
T& operator*(void) {assert(valid); return *Get();}
T const* const operator->(void) const {assert(valid); return Get();}
T* const operator->(void) {assert(valid); return Get();}
void Clear(void)
{
//This clears the value of this optional variable and makes it invalid once again.
if(valid)
{
valid = false;
Destroy();
}
}
};

Share this post


Link to post
Share on other sites
Advertisement
The version of the new operator used is called "placement new". It is used to construct an object at a particular address. No memory is allocated on the heap, so no corresponding call to a delete operator is required.

However, the code is not portable as it does not take in to account the alignment of the type parameter. It may or may not contain other errors, but that's one that's made quite often in this kind of code.

Share this post


Link to post
Share on other sites
Instead of using [color="#000088"]char data[color="#666600"][size[color="#666600"]]; why don't you change the template parameter to take the type of the item being stored? That would probably solve any alignment issues. Oh, is it so that you can suppress the destruction? Surely there must be a better way to do it? Hmm.

Also, instead of a dangerous assignment operator, why don't you use the copy-and-swap idiom? That solves the exception safeness of it.

I've never used boost optional, what's the difference between it and yours?

Share this post


Link to post
Share on other sites

Also, instead of a dangerous assignment operator, why don't you use the copy-and-swap idiom? That solves the exception safeness of it.

Actually it doesn't solve the general case, since the primary std::swap template can throw due to internal copies being made. A 'valid' flag would still be needed unless the 'T' was allocated on the heap, thus making the swap no-throw.


I've never used boost optional, what's the difference between it and yours?
[/quote]
boost optional gets the alignment stuff as correct as possible given the constraints of C++98. I'm not sure why the OP is seeking an alternative...

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!