Skip to main content
gamedev.net
🔒 Locked

Array of objects

Started by SunDog Feb 14, 2007 at 7:14 AM 10 replies 1.7k views
Original Post
SunDog
SunDog
Lets say I create an array of objects in C++ Object* array_of_objs; array_of_objs = new Object[10]; 1) Is any construct called? If so which one? The default constructor ? 2) Is there any way to call a constructor on each element after the array has been created?
snk_kid
snk_kid
Quote:
Original post by SunDog
Is any construct called? If so which one? The default constructor ?


Yep & Yep, if no default exists you'll get a compile-time error.

Quote:
Original post by SunDog
2) Is there any way to call a constructor on each element after the array has been created?


There are a thew methods of either getting round the problem or achieving exactly what you want to achieve for instance:

#include <vector>std::vector<Object> v(size, Object(...));
Tsylatac
Tsylatac
Yes, the default constructor will be called for each object. You can't call a constructor on an object after it has been constructed (hence why it's called a constructor ;)), however you can set an object in the array equal to a new object constructed using that constructor, for example if you have an object constructor that takes an integer:

array_of_objs[3] = Object(233);

In which case the memory that array_of_objs[3] points at will be overwritten with the new Object you have constructed.

Edit: I didn't know about that particular vector constructor, looks fairly useful!
----------Little known fact: Tsylatac is Catalyst backwards :).
Oxyd
Oxyd
Quote:
Original post by SunDog
1) Is any construct called? If so which one? The default constructor ?

Yes, there are ten objects created, all of them are initialized by the default constructor. That is -- ten default constructors are called, one for each object.

Quote:
Original post by SunDog
2) Is there any way to call a constructor on each element after the array has been created?


Nope. After the array has been created, the objects are already initialized. You can't call constructor on an initialized object. AFAIK, you can't create an array that contains objects of such types that do not provide default constructors.

It should be recommended that you can use std::vector instead of a raw C-style array. This way, you won't have to care about the memory allocation and deallocation yourself and you will be able to create arrays of types that do not provide default constructors.

#include <vector>class foo {  public:    // No default constructor here.    explicit foo(int) { }};int main() {  std::vector<foo> array(10, foo(42));  // Create an array of ten elements                                         // of type foo, initialized with                                              // the value 42.}
snk_kid
snk_kid
Quote:
Original post by Tsylatac
however you can set an object in the array equal to a new object constructed using that constructor, for example if you have an object constructor that takes an integer:

array_of_objs[3] = Object(233);

In which case the memory that array_of_objs[3] points at will be overwritten with the new Object you have constructed.


Now what happens if either constructor and/or the assignment operation is costly? ;) std::vector gets round this by separating allocation/deallocation. You could do this yourself but the code is error prone, unsafe, low-level and ulgy i.e:

#include <new> // placement new operatorObject* objs = ::operator new(sizeof(Object) * N); // allocation onlyfor(int i = 0; i < N; ++i)    ::new(objs + i) Object(....); // in-place construction......for(int i = 0; i < N; ++i) // this must be done for NON-POD types   (objs + i)->~Object(); // destructs only::operator delete(objs); // deallocates only


This is one of the reasons why i (and others) torment people to use std::vector.

[Edited by - snk_kid on February 14, 2007 8:40:21 AM]
SunDog
SunDog
Thanks for the quick replies. The reason I'm not using std::vector is I want this to be super-efficient. Its a fairy static data structure that gets created once at the beginning of the program (its elements get modifed, but do not get added/removed from the array). So I only see std::vector increasing space requirements and slowing down execution speed. As I plan on having the size of the array number in the tens, possibly hundreds, of millions, this is kind of important :-) If it makes you feel any better I'm using std::vector, std::list and for everything else (not to mention std::string)

Its really not that big of a deal - i was just wondering offhand.

snk_kid
snk_kid
Quote:
Original post by SunDog
Thanks for the quick replies. The reason I'm not using std::vector is I want this to be super-efficient. Its a fairy static data structure that gets created once at the beginning of the program (its elements get modifed, but do not get added/removed from the array). So I only see std::vector increasing space requirements and slowing down execution speed. As I plan on having the size of the array number in the tens, possibly hundreds, of millions, this is kind of important :-)


It's up to you however it does sound as though you've been ill informed. The efficency of std::vector in a release build (i.e. with optimizations on, of modern implementations) is virtually no different than a raw array, you can specify the exact size or capacity. Infact in alot of cases it can be more efficent than raw array usage because it takes advantage of optimizations you may be unaware of or just forget to take.

The only (insignicant) overhead std::vector may have is most typical implementations use 3 pointers but for the majority of the time you'll store the size of a raw array somewhere anyways.

[Edited by - snk_kid on February 14, 2007 8:11:13 AM]
Bregma
Bregma
Quote:
Original post by SunDog
Thanks for the quick replies. The reason I'm not using std::vector is I want this to be super-efficient.


Premature Optimization Rule 1: Don't do it.

Premature Optimization Rule 2 (for experts only): Don't do it (yet).

Do you have numbers backing up your choice of arrays over vectors, or are you relying on superstition and religious faith?

--smw
Stephen M. Webb
Professional Free Software Developer
SunDog
SunDog
Quote:
Original post by Bregma
Quote:
Original post by SunDog
Thanks for the quick replies. The reason I'm not using std::vector is I want this to be super-efficient.


Premature Optimization Rule 1: Don't do it.

Premature Optimization Rule 2 (for experts only): Don't do it (yet).

Do you have numbers backing up your choice of arrays over vectors, or are you relying on superstition and religious faith?

--smw


Well I don't see how std::vector could possibly any better than what I'm doing for these reasons:

- Access to the array is controlled through class encapsulation, so there are no worries about out-of-bounds data corruption. I have this encapsulation whether I used std::vector or not, and would still have my bounds checking code anyway as I would generate my own errors if an out-of-bounds access request occurred.

- std::vector doesn't store the objects themselves, but the pointers to them. This may seem insignificant, but when you have tens or hundreds of millions of objects, thats tens of hundreds of megabytes of space just for one 32-bit pointer

- The size of the array is static for its lifetime, so allocation/deallocation of objects within the array isn't necessary

- It doesn't buy me anything in terms of writability or readability of code

- If I do eventually find a use for std::vector, I transparently replace the array with it as array deferences are implemented

- If you are right, doing it this way gives yet even more empirical evidence for the superiority of std::vector!
snk_kid
snk_kid
Quote:
Original post by SunDog
- Access to the array is controlled through class encapsulation, so there are no worries about out-of-bounds data corruption. I have this encapsulation whether I used std::vector or not, and would still have my bounds checking code anyway as I would generate my own errors if an out-of-bounds access request occurred.


std::vector has both checked & unchecked access.

Quote:
Original post by SunDog
- std::vector doesn't store the objects themselves, but the pointers to them. This may seem insignificant, but when you have tens or hundreds of millions of objects, thats tens of hundreds of megabytes of space just for one 32-bit pointer.


No, no, no, your quite wrong, as i've mentioned already std::vector essentially works in the method i showed where allocation/deallocation & construction/destruction is separate, further more one can give custom allocator types to any standard library container. It does not work on the concept of an array of pointers, where did you get that idea from?

It will only ever do that if you explicitly tell it to do so with the type you give it.

Quote:
Original post by SunDog
- The size of the array is static for its lifetime, so allocation/deallocation of objects within the array isn't necessary


As i've mentioned already you can specify the exact size or capacity of an instance of std::vector and you've proved my point that the over head of just three pointers is insignifcant since your storing the size anyways.

I'm a little confused now are we talking about a statically allocated array or dynamically allocated one? because the original code says the latter but it looks like your talking about the former.
SunDog
SunDog
Quote:
Original post by snk_kid
I'm a little confused now are we talking about a statically allocated array or dynamically allocated one? because the original code says the latter but it looks like your talking about the former.


Its dynamically allocated, but its only done once at the start of the program and it lifetime is the length of the program.
ToohrVyk
ToohrVyk
Quote:
Original post by SunDog
Access to the array is controlled through class encapsulation, so there are no worries about out-of-bounds data corruption. I have this encapsulation whether I used std::vector or not, and would still have my bounds checking code anyway as I would generate my own errors if an out-of-bounds access request occurred.


When using an optimizing compiler, a will create the same code whether a is a pointer or a vector. C arrays sometimes incur one less indirection, but you stated that you were not using a C array but a pointer anyway. If you're doing pointer arithmetic with your storage, then vector code may or may not be identical, but you should consider improving performance anyway by reducing aliasing problems (in particular, by using subscripts).

Quote:
std::vector doesn't store the objects themselves, but the pointers to them. This may seem insignificant, but when you have tens or hundreds of millions of objects, thats tens of hundreds of megabytes of space just for one 32-bit pointer


You are spewing misinformed propaganda. It's quite possible that you don't know or don't bother knowing how std::vector works, and that's okay with me. However, if you start making incorrect statements as the above as if they were true, that's not okay with me anymore. std::vector stores its objects in contiguous storage in memory, just as a C array. There is no hidden overhead that would become dangerous when storing many objects.

Quote:
The size of the array is static for its lifetime, so allocation/deallocation of objects within the array isn't necessary


You still have one allocation and one allocation per object (on startup and shutdown).

Quote:
It doesn't buy me anything in terms of writability or readability of code


It would help you using a constructor other than the default one, perhaps even different constructors. Or perhaps initializing elements by reading them from a file. Besides, as you've mentioned, the difference between using an array and using a vector is a simple matter of a typedef and changing a line of initialization code.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.