Jump to content
  • Advertisement
Sign in to follow this  
Jiia

Zeroing Complex Types

This topic is 4840 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 want to do something very basic with a template function. The function receives an array, and adds a subset to it. It can add the subset in the center of the array, the end, or the beginning. This is basically how it works: newArray = allocate[?]; copy( newArray + ?, oldArray + ?, ? ); - actually two calls for start and end deallocate oldArray; I'm not wanting to copy the data, I want to move it. Otherwise the inner-working allocations would get out of hand. The problem is that the destructor of a certain type is deleting its memory when I deallocate the old array. What would be the proper way to handle this? I thought about a memset on the whole chunk before I delete, but I know this will totally erase v-tables. I just want to delete the instance data without calling destructors. If there is no better way to handle this, is it safe to zero v-tables before deleting objects? My guess is no, but what effect would this have? Thanks for suggestions

Share this post


Link to post
Share on other sites
Advertisement
If you zero a vtable, it'll probably crash your program when it gets deleted, assuming a virtual destructor.

But I'm not really sure what you're trying to accomplish, so I can't give any advice.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jiia
I want to do something very basic with a template function. The function receives an array, and adds a subset to it. It can add the subset in the center of the array, the end, or the beginning. This is basically how it works:

newArray = allocate[?];
copy( newArray + ?, oldArray + ?, ? ); - actually two calls for start and end
deallocate oldArray;

I'm not wanting to copy the data, I want to move it. Otherwise the inner-working allocations would get out of hand. The problem is that the destructor of a certain type is deleting its memory when I deallocate the old array. What would be the proper way to handle this?


Probably to have the object deep copy it's objects. E.g. instead of:

class foo {
type * pointer;
public:
foo() {
pointer = new type;
}
~foo() {
delete pointer;
}
foo & operator=( const foo & other ) {
pointer = other.pointer; //just copy the address
return *this;
}
};






You do:

class foo {
...
foo & operator=( const foo & other ) {
pointer = other.pointer->clone(); //where clone() returns a new class of that type...
//or, if pointer will allways point to type, not a derived class:
pointer = new type( *(other.pointer) );
return *this;
}
};


This way, each foo has it's own instance of the pointed to data - changing it in one foo won't change it in another, nor will deleting it in one foo delete it for another. However, if the foos should be sharing the resource pointed to by the pointer (but not deleting it multiple times, or when one is still using it), then you should probably use a "shared pointer" such as boost::shared_ptr:

class foo {
boost::shared_ptr< type > pointer;
public:
foo() {
pointer = boost::shared_ptr< type >( new type );
}
~foo() {
//no delete, when zero boost::shared_ptr's point at the item, it will be deleted automatically
}
foo & operator=( const foo & other ) {
pointer = other.pointer;
return *this;
}
};





Boost C++ Libraries

Share this post


Link to post
Share on other sites
I'm trying to create a function which takes an array and returns a new array containing all of the same elements of the old array as well as a new empty subset inserted at a variable point. The function is templated, and I want it to work well with basic and complex types.

I need a built in nullify or transfer-instance operation. I can't think of a correct way to do this :)

Thanks for the help, and I'm sorry I haven't been clear enough.

Share this post


Link to post
Share on other sites
"Moving" something on a computer logically consists of copying it and then erasing the original; there isn't really much else you can do. Consider how your operating system handles file copies, for example.

Anyway, have you considered just using a std::list, and the .splice() member function?

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
"Moving" something on a computer logically consists of copying it and then erasing the original; there isn't really much else you can do.

But that's exactly what I want to do. I want to copy the instances in the array without copying all of the data that complex types may have allocated.

For example, consider an array of SomeClass. SomeClass may be capable of allocating a huge chunk of data on it's own in some process. I want to copy the array of SomeClass instances so their huge chunk of memory simply moves to other instances, causing the old instances to revert back to their construction stage. I don't want to reallocate that huge chunk of memory for each SomeClass instance, considering the old one is just going to be deleted.

What about swapping? Would it be safe to swap the instances? Instead of simply copying the old over onto the new, I could copy the new back to the old as well. This would even take care of situations where an object may allocate data on construction. It would be deleted as though it had just been constructed there. Unfortunately, I'm not even sure how I could swap them cleanly. I would have to make an additional buffer of some kind.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jiia
Quote:
Original post by Zahlman
"Moving" something on a computer logically consists of copying it and then erasing the original; there isn't really much else you can do.

But that's exactly what I want to do. I want to copy the instances in the array without copying all of the data that complex types may have allocated.

What about swapping? Would it be safe to swap the instances? Instead of simply copying the old over onto the new, I could copy the new back to the old as well. This would even take care of situations where an object may allocate data on construction. It would be deleted as though it had just been constructed there. Unfortunately, I'm not even sure how I could swap them cleanly. I would have to make an additional buffer of some kind.


Swapping is indeed what you'll need to do. Here's the "portable" way to do this... assuming we have an array of size 10, and we want to insert another 5 elements in the middle:

const size_t original_size = 10;
const size_t insertion_start = 5;
const size_t new_elements = 5;
int * original = new int[ original_size ];

int * new_array = new int[ original_size + new_elements ];

for ( size_t i = 0 ; i < insertion_start ; ++i ) {
std::swap< int >( original , new_array );
}
for ( size_t i = insertion_start ; i < insertion_start + new_elements ; ++i ) {
new_array = int( 13 ); //assign new values
}
for ( size_t i = insertion_start + new_elements ; i < original_size + new_elements ; ++i ) {
std::swap< int >( original[i - new_elements] , new_array );
}

delete[] original;


...


delete[] new_array;




This relies on the classes themselves having a specialization of std::swap. The fallback version is implemented akin to:

template < typename type > void swap( type & a , type & b ) {
type temp = a;
a = b;
b = temp;
}

Which is one copy construction and two copys assignments.

Here's an example:

#include <algorithm>
#include <vector>

class possibly_contains_huge_array;

namespace std {
inline void swap( possibly_contains_huge_array & a , possibly_contains_huge_array & b );
}

class possibly_contains_huge_array {
int * pointer_to_possibly_huge_newed_array;
std::vector< int > possibly_huge_vector;
public:
friend inline void std::swap( possibly_contains_huge_array & a , possibly_contains_huge_array & b ) {
std::swap( a.pointer_to_possibly_huge_newed_array , b.pointer_to_possibly_huge_newed_array );
std::swap( a.possibly_huge_vector , b.possibly_huge_vector );
}
};





Notes:
1) First we must forward-declare our specialization within the std namespace. This is okay because we're specializing an existing template, one of the very few exceptions to the "dont dick around in the std namespace" rule.

2) In order to access the private variables of possibly_contains_huge_array, we need to make the function a friend of the class.

3) In this example, I also implemented the function within the class. I know this is legal without the namespace issue, and GCC compiles this without complaint, so I believe it's valid.

4) I simply called std::swap on all the members. There's allready a specialization of std::swap for std::vector, and there's no way to make the swapping of pointers more efficient than:

type * temp = a;
a = b;
b = temp;


Which is what the template will be defaulting to anyways.

Share this post


Link to post
Share on other sites
Also, to continue (in a new post since my internet is churning):

If you'd rather copy-construct the new, inserted values, instead of default-constructing then assigning, you'd need to use "placement new" and an allocator that dosn't construct the values beforehand on your behalf. I'm not going to go into this, because it's tantemount to implementing std::vector - if you just want the behavior, just use std::vector. If you want to know how it's done, look into it's implementation. The headers are allready on your system, after all.

HTH,
-Mike

Share this post


Link to post
Share on other sites
You're being incredibly helpful.. and hey.. look, I didn't have your rating maxed. This is the first time in a while I've actually been able to rate up a helpful poster. I usually assume I've maxed out helpful people such as yourself. Only a few points, but it's the thought that counts :P

Seriously, I don't think I could ask for more details. Thanks a lot for your help.

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!