views:

1209

answers:

11

I have an array, called x, whose size is 6*sizeof(float). I'm aware that declaring:

float x[6];

would allocate 6*sizeof(float) for x in the stack memory. However, if I do the following:

float *x;   // in class definition

x = new float[6];   // in class constructor

delete [] x;    // in class destructor

I would be allocating dynamic memory of 6*sizeof(float) to x. If the size of x does not change for the lifetime of the class, in terms of best practices for cleanliness and speed (I do vaguely recall, if not correctly, that stack memory operations are faster than dynamic memory operations), should I make sure that x is statically rather than dynamically allocated memory? Thanks in advance.

A: 

Yes, declaring the array statically will perform faster.

This is very easy to test, just write a simple wrapping loop to instantiate X number of these objects. You can also step through the machine code and see the larger number of OPCODEs required to dynamically allocate the memory.

hobodave
+6  A: 

Declaring the array of fixed size will surely be faster. Each separate dynamic allocation requires finding an unoccupied block and that's not very fast.

So if you really care about speed (have profiled) the rule is if you don't need dynamic allocation - don't use it. If you need it - think twice on how much to allocate since reallocating is not very fast too.

sharptooth
Why do you use the word "statically" in this context? It means something totally different than "on the stack"...
xtofl
(oh I see, it's in the question...)
xtofl
@xtofl: Yes, that was not a fortunate term to use here. Fixed.
sharptooth
A: 

Composition is more efficient, being faster, lower memory overhead and less memory fragmentation.

You could do something like this:

template <int SZ = 6>
class Whatever {
   ...
   float floats[SZ];
};
Tim Sylvester
A: 

Use the stack allocated memory whenever possible. It will save you from the headaches of deallocating the memory, fragmentation of your virtual address space etc. Also, it is faster compared to the dynamic memory allocation.

Naveen
A: 

If yo allocate the arraty statically, there will only be one instance of it. The point of using a class is that you want multiple instances. There is no need to allocate the array dynamically at all:

class A {
   ...
   private:
      float x[8];
};

is what you want.

anon
"If you allocate the array statically, there will only be one instance of it. The point of using a class is that you want multiple instances." - Huh? There would be an array for every instance of his object regardless of whether it was dynamically allocated in the class constructor, or statically allocated as a member variable.
hobodave
@hobodave: That's not correct. There is a difference between allocating the objects on stack and the static objects inside a class. What Neil is referring is the second one. Then there will only one instance of the array irrespective of number of instances of the class.
Naveen
@hobodave No matter where ikt appears, a static variable omly ever has a single instance.
anon
Ah, the OP used the word "statically" to mean, incorrectly, allocated on the stack. I knew what he was *trying* to say, but continued to use his incorrect terminology.
hobodave
Neil, I'd like to remove my -1, but it's too old. Can you edit your answer?
hobodave
+1  A: 

TBH data on the stack generally sits in the cache and hence it is faster. However if you dynamically allocate something once and then use it regularly it will also be cached and hence pretty much as fast.

The important thing is to avoid allocating and deallocating regularly (ie each time a function is called). If you justa void doing regular allocation and deallocations (ie allocate and deallocate once only) then a stack and heap allocated array will preform pretty much as quickly as each other.

Goz
+3  A: 

Using an array member will be cleaner (more succinct, less error prone) and faster as there is no need to call allocation and deallocation functions. You will also tend to improve 'locality of reference' for the structure being allocated.

The two main reasons for using dynamically allocated memory for such a member are where the required size is only known at run time, or where the required size is large and it is known that this will have a significant impact on the available stack space on the target platform.

Charles Bailey
A: 

There are more variables at play here:

  1. The size of the array vs. the size of the stack: stack sizes are quite small compared to the free store (e.g. 1MB upto 30MB). Large chunks on the stack will cause stack overflow

  2. The number of arrays you need: large number of small arrays

  3. The lifetime of the array: if it's only needed locally inside a function, the stack is very convenient. If you need it after the function has exited, you must allocate it on the heap.

  4. Garbage collection: if you allocate it on the heap, you need to clean it up manually, or have some flavour of smart pointers do the work for you.

xtofl
+1  A: 

Static allocation is faster (no need to ask to memory ) and there's no way you will forget to delete it or delete it with incorrect delete operator (delete instead of delete[]).

Construction an usage of dynamic/heap data is consists of the following steps:

  • ask for memory to allocate the objects (calling to new operator). If no memory a new operator will throw bad_alloc exception.
  • creating the objects with default constructor (also done by new)
  • release the memory by user (by delete/delete[] operator) - delete will call to object destructor. Here a user can do a lot of mistakes:
    • forget to call to delete - this will lead to memory leak
    • call to not correct delete operator (e.g. delete instead of delete[]) - bad things will happen
    • call to delete twice - bad things can happen

When using static objects/array of objects, there's no need to allocate memory and release it by user. This makes code simpler and less error-prone.

So to the conclusion, if you know your size on the array on at compilation time and you don't matter about memory (maybe at runtime I'll use not entries in the array), static array is obviously preferred one. For dynamic allocated data it worth looking for smart pointers (here)

dimba
+1  A: 

Don't confuse the following cases:

int global_x[6];        // an array with static storage duration

struct Foo {
    int *pointer_x;     // a pointer member in instance data
    int member_x[6];    // an array in instance data
    Foo() { 
        pointer_x = new int[6];    // a heap-allocated array
    }
    ~Foo() { delete[] pointer_x; }
};

int main() {
    int auto_x[6];           // an array on the stack (automatic variable)
    Foo auto_f;              // a Foo on the stack
    Foo *dyn_f = new Foo();  // a heap-allocated Foo.
}

Now:

  • auto_f.member_x is on the stack, because auto_f is on the stack.
  • (*dyn_f).member_x is on the heap, because *dyn_f is on the heap.
  • For both Foo objects, pointer_x points to a heap-allocated array.
  • global_x is in some data section which the OS or runtime creates each time the program is run. This may or may not be from the same heap as dynamic allocations, it doesn't usually matter.

So regardless of whether it's on the heap or not, member_x is a better bet than pointer_x in the case where the length is always 6, because:

  • It's less code and less error-prone.
  • Your object only needs a single allocation if the object is heap-allocated, instead of 2.
  • Your object requires no heap allocations if the object is on the stack.
  • It uses less memory in total, because of fewer allocations, and also because there's no need for storage for the pointer value.

Reasons to prefer pointer_x:

  • If you need to reallocate during the lifetime of the object.
  • If different objects will need a different size array (perhaps based on constructor parameters).
  • If Foo objects will be placed on the stack, but the array is so large that it won't fit on the stack. For instance if you've got 1MB of stack, then you can't use automatic variables which contain an int[262144].
Steve Jessop
A: 

As mentioned in another reply, large objects can not be allocated on the stack because you are not sure what is the stack size. In interests of portability, large objects or objects with variable sizes should always be allocated on the heap.

There has been a lot of development in the malloc/new routines now provided by the operating system (for example, Solaris's libumem). Dynamic memory allocation is often not a bottleneck.