Jump to content
  • Advertisement
Sign in to follow this  
SirLuthor

Explicit Construction/Destruction

This topic is 4900 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

Hiya folks, I've got another question for your worthy minds to solve which evades me [smile] Anyway, I'm roughing out a memory manager right now, and I just realized that I have no idea at all how one would go about calling the constructor and destructor of an object without actually freeing the memory. Let's imagine I have a StrongPointer class, templated. It has a void pointer to some allocated memory as a member, and I want to be able to call the constructor and destructor of the template type on that memory at will, such as when it has no more references, or whatever. Note that this is not a good example really, and it does not really reflect on what I'm actually doing, it's simply there to possibly help explain what my explanation bungled [smile] I found out how to use placement new, and that should be relatively easy to use with templates, but the methods I saw of calling the destructors without de-allocting the memory seem to be ill-suited to use with templates. Annnyway, if anyone could point out to me how I would do this, I'd much appreciate it.

Share this post


Link to post
Share on other sites
Advertisement

void * someMemory = malloc( sizeof( TheClass ) );
// construction
obj = new( someMemory ) TheClass( constructor arguments );
// destruction
obj->~TheClass();
// "someMemory" should be separately freed
free( someMemory );

Share this post


Link to post
Share on other sites
Yes, but I still don't see why calling the destructor manually is usefull... It gets called on the call to delete/free anyway.

Toolmaker

Share this post


Link to post
Share on other sites
A C++ variation on hplus0603's code:


void * someMemory = ::operator new( sizeof( TheClass ) );

// construction

obj = new( someMemory ) TheClass( constructor arguments );

// destruction

obj->~TheClass();

// "someMemory" should be separately freed

::operator delete( someMemory);




Toolmaker - A C++ vector allocates memory and constructs elements separately. It will allocate more memory than needed to allow for growth, and constructs the new elements in the preexisting memory as it goes. And in reverse, will destroy the elements without deallocating the memory, until the vector itself gets destroyed.

Share this post


Link to post
Share on other sites
Just to clarify, the free call will not call the destructor automatically as Toolmaker said. In most situations when using placement new you will need to manually call the destructor.

Share this post


Link to post
Share on other sites
The operator new allocates the needed memory, and then calls the contructor. The operator delete calls the destructor then frees the memory.

If you did use malloc (or some other memory allocation method), you would need to call the constructors and destructors of classes explicitly. In C++, unless you are using your own memory management system, you should be using new, new[], delete, and delete[] to allocate and deallocate memory.

Often the constructors and destructors are called directly in the case of using memory pooling (even then there is a form of new that can be used to to point at a spefic memory allocation). Something like this would be used if you used malloc to allocate a giant heap of memory to be used. You wouldn't want to call delete on something that was created in that pool of memory, since you don't actually want to release the memory completely from memory, you just want to make it avaiable, do you would explicitly call the destructor to safely destroy the object. (Note: This is basically another topic all together).

Share this post


Link to post
Share on other sites
Quote:
Original post by Rattrap
The operator new allocates the needed memory, and then calls the contructor. The operator delete calls the destructor then frees the memory.

Nearly, but actually the new operator allocates memory (via operator new) and then calls the constructor. The delete operator calls the destructor and then frees the memory (via operator delete). There is a difference between the new operator and operator new (and equivalently for delete). The latter deals in uninitialised memory and can be overloaded. The former deals in initialised objects and cannot be overloaded.

Enigma

Share this post


Link to post
Share on other sites
I'm sorry, was I not very clear or something? I'm fully cognizant that new/delete call the constructor and destructor, and I know that malloc/free do not. I cannot use new and delete, because I'm working on a memory manager, which doesn't allow just deleting chunks of memory in the middle of a heap. Thus I need to be able to call the destructor of an object of an unknown type without freeing the memory, thus effectively deleting dead objects, which keeping the memory for later usage.

The key words there are of an unknown type, thus, I cannot explicitly call the destructor like so many people told me to do, that is:
foo->~MyClass();
Because, the type of object being a template argument, what happens when the object type is not a MyClas, but a Bar, or something else?

Share this post


Link to post
Share on other sites
Toolmaker already answered your question. Yes, you can use the template argument as the destructor name:
#include <iostream>
#include <new>
#include <string>

class Test1
{
public:

Test1()
:
a(7),
b('z'),
c(3.14f)
{
std::cout << "Test1 constructor\n";
}
~Test1()
{
std::cout << "Test1 destructor\n";
}
void print() const
{
std::cout << "Test1\n\t" << a << "\n\t" << b << "\n\t" << c << '\n';
}

private:

int a;
char b;
float c;

};

class Test2
{
public:

Test2()
:
a(7),
b(new char('F')),
c("This is a string")
{
std::cout << "Test2 constructor\n";
}
~Test2()
{
std::cout << "Test2 destructor\n";
}
void print() const
{
std::cout << "Test2\n\t" << a << "\n\t" << *b << "\n\t" << c << '\n';
}

private:

int a;
char * b;
std::string c;

};

template < typename TYPE >
class Wrapper
{

public:

Wrapper()
:
object_(static_cast< TYPE * >(::operator new(sizeof(TYPE))))
{
}
~Wrapper()
{
::operator delete(object_);
}
void allocate()
{
new (object_) TYPE();
}
void release()
{
object_->~TYPE();
}
TYPE const * operator->() const
{
return object_;
}

private:

TYPE * object_;

};

int main()
{
Wrapper< Test1 > wrapperOne;
Wrapper< Test2 > wrapperTwo;
wrapperTwo.allocate();
wrapperOne.allocate();
wrapperOne->print();
wrapperTwo->print();
wrapperOne.release();
wrapperTwo.release();
wrapperOne.allocate();
wrapperOne->print();
wrapperOne.release();
}

Enigma

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!