Jump to content
  • Advertisement
Sign in to follow this  
dmatter

array of a class without default constructors

This topic is 4887 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 know when an array of a class is created the default constructor for that class and therefore when no default constructor is present a compile error occurs. Yet I know that the STL vector can create an array of objects without a default constructor. I also know it does this by using a prototype of the same class which it uses to default all the elements in the vector array. What I want to know is how is this done? I need to create an array of a class that cannot have a default constructor and without using the stl vector. Any ideas? thanks

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
Actually, the only reason why STL containers (say, vector) can be created using types with no default constructor is because it does not allocate memory to the internal pointer until you do a resize(), etc operation. The same occurs if you use the vector constructor which takes an initial size.

There is no way to do array initialization of objects using new. Only the default constructor is called, and if not available, it will not compile.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Anonymous Poster
The same occurs if you use the vector constructor which takes an initial size.



class A
{
public:
A(const int src_x)
{
x = src_x;
}

int x;
};

int main(void)
{
vector<A> a; // OK
vector<A> a(50); // bomb
vector<A> a(50, A(10)); // OK, because you are providing an object to use as the initializer

return 0;
}

Share this post


Link to post
Share on other sites
You can use an array of pointers to the object, or you can allocate raw memory and use placement new (Though this is dangerous and not recommended). If at all possible, prefer to give the object a default constructor.

Share this post


Link to post
Share on other sites
Ok, this is a hack... a ugly one at that. But does the trick most of the time.


//beware... dragons ahead.
#include <new>
#include <iostream>
struct A
{
A(int x): x( x){ std::cout << "A::A()\n";}
A(const A &a): x( a.x){ std::cout << "A::A(A)\n";}
~A(void){ std::cout << "A::~A()\n";}
int x;
};

template <typename T>
void raw_init( void *dst, size_t n, const T &prototype)
{
T *p( reinterpret_cast<T*>(dst));
for(size_t i = 0; i != n; ++i)
new (p++) A(prototype);
}

template <typename T>
void raw_kill( T *p, size_t n)
{
for(size_t i = 0; i != n; ++i)
p++->~T();
}


int main(void)
{
// A a[10];//bombs
//hold on to thy hat...
const int N = 10;
unsigned char data[sizeof(A) * N];//declare storage
raw_init( data, N, A(10));
A (&a)[N] = reinterpret_cast<A(&)[N]>(data);//quite horrid
//but from here we can use it just as if we would have declared our static array :)
//...
//dont forget to kill the whole mess to :)
raw_kill( a, N);
}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Sweet mother of...

Ouch. :) Nice technique though!

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Actually, the only reason why STL containers (say, vector) can be created using types with no default constructor is because it does not allocate memory to the internal pointer until you do a resize(), etc operation. The same occurs if you use the vector constructor which takes an initial size.

There is no way to do array initialization of objects using new. Only the default constructor is called, and if not available, it will not compile.


Your quite wrong [smile], the standard library containers are parameterized by allocator type, allocator concept seperates de/allocation and construction/destruction (very low-level not generally recommend unless your implementing containers or something similar). If you want to seperate it the general idea is:


#include <new>

// or std::malloc, anything that allocates raw memory only
void* buf = ::operator new(sizeof(foo)); // allocate only

foo* f = new(buf) foo(); // construct only (placement new)
// (any constructor can be used including copy constructor)

f->~foo(); // destruct only
// you must do this with placement new

::operator delete(buf); // deallocate only


Thus the technique can be extended to allocate a buffer/array to. The standard library also provides a set of algorithms that work with uninitialized memory aswell.

Note as already mentioned you could just create an array of pointers instead because the above technique is not recommended for general use (or just use the standard library containers [smile]).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
My bad, I should not have said "the only reason". :)

The example still stands though... construction of the container only works when the container's default constructor is called.

How it allocates the memory is not really important.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
My bad, I should not have said "the only reason". :)

The example still stands though... construction of the container only works when the container's default constructor is called.

How it allocates the memory is not really important.


Well it actually is, and for an enlightening exercise ponder the differance between vector::resize and vector::reserve.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Touche. Very good point, I did not think to check that.

When one writes their own allocator though, is this method of memory allocation required?

The reason why I am saying that it is unimportant is that the underlying implementation of memory allocation has nothing to do with the fact that if you create a container of objects with no default constructor, you must provide an example object that was manually constructed using whatever non-default constructor you choose.

Why else would the standard require this, other than to protect those who use allocators which do not rely on placement new?

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!