I have to do an assignment for my class and it says not to use Static arrays, only Dynamic arrays. I've looked in the book and online, but I don't seem to understand.
I thought Static was created at compile time and Dynamic at runtime, but I might be mistaking this with memory allocation.
Can you explain the difference between static array and dynamic array in C++?
Static arrays are created on the stack, and have automatic storage duration: you don't need to manually manage memory, but they get destroyed when the function they're in ends. They necessarily have a fixed size at compile time:
int foo[10];
Arrays created with operator new[] have dynamic storage duration and are stored on the heap (technically the "free store"). They can have any size during runtime, but you need to allocate and free them yourself since they're not part of the stack frame:
int* foo = new int[10];
delete[] foo;
static is a keyword in C and C++, so rather than a general descriptive term, static has very specific meaning when applied to a variable or array. To compound the confusion, it has three distinct meanings within separate contexts. Because of this, a static array may be either fixed or dynamic.
Let me explain:
The first is C++ specific:
A static class member is a value that is not instantiated with the constructor or deleted with the destructor. This means the member has to be initialized and maintained some other way. static member may be pointers initialized to null and then allocated the first time a constructor is called. (Yes, that would be static and dynamic)
Two are inherited from C:
within a function, a static variable is one whose memory location is preserved between function calls. It is static in that it is initialized only once and retains its value between function calls (use of statics makes a function non-reentrant, i.e. not threadsafe)
static variables declared outside of functions are global variables that can only be accessed from within the same module (source code file with any other #include's)
The question (I think) you meant to ask is what the difference between dynamic arrays and fixed or compile-time arrays. That is an easier question, compile-time arrays are determined in advance (when the program is compiled) and are part of a functions stack frame. They are allocated before the main function runs. dynamic arrays are allocated at runtime with the "new" keyword (or the malloc family from C) and their size is not known in advance. dynamic allocations are not automatically cleaned up until the program stops running.
It's important to have clear definitions of what terms mean. Unfortunately there appears to be multiple definitions of what static and dynamic arrays mean.
Static variables are variables defined using static memory allocation. This is a general concept independent of C/C++. In C/C++ we can create static variables with global, file, or local scope like this:
int x[10]; //static array with global scope
static int y[10]; //static array with file scope
foo() {
static int z[10]; //static array with local scope
Automatic variables are usually implemented using stack-based memory allocation. An automatic array can be created in C/C++ like this:
foo() {
int w[10]; //automatic array
What these arrays , x, y, z, and w have in common is that the size for each of them is fixed and is defined at compile time.
One of the reasons that it's important to understand the distinction between an automatic array and a static array is that static storage is usually implemented in the data section (or BSS section) of an object file and the compiler can use absolute addresses to access the arrays which is impossible with stack-based storage.
What's usually meant by a dynamic array is not one that is resizeable but one implemented using dynamic memory allocation with a fixed size determined at run-time. In C++ this is done using the new operator.
foo() {
int *d = new int[n]; //dynamically allocated array with size n
But it's possible to create an automatic array with a fixes size defined at runtime using alloca:
foo() {
int *s = (int*)alloca(n*sizeof(int))
For a true dynamic array one should use something like std::vector in C++ (or a variable length array in C).
What was meant for the assignment in the OP's question? I think it's clear that what was wanted was not a static or automatic array but one that either used dynamic memory allocation using the new operator or a non-fixed sized array using e.g. std::vector.
I think the semantics being used in your class are confusing. What's probably meant by 'static' is simply "constant size", and what's probably meant by "dynamic" is "variable size". In that case then, a constant size array might look like this:
int x[10];
and a "dynamic" one would just be any kind of structure that allows for the underlying storage to be increased or decreased at runtime. Most of the time, the std::vector class from the C++ standard library will suffice. Use it like this:
std::vector<int> x(10); // this starts with 10 elements, but the vector can be resized.
std::vector has operator[] defined, so you can use it with the same semantics as an array.
Static arrays are allocated memory at compile time and the memory is allocated on the stack. Whereas, the dynamic arrays are allocated memory at the runtime and the memory is allocated from heap.
int arr[] = { 1, 3, 4 }; // static integer array.
int* arr = new int[3]; // dynamic integer array.
I think in this context it means it is static in the sense that the size is fixed.
Use std::vector. It has a resize() function.
You could have a pseudo dynamic array where the size is set by the user at runtime, but then is fixed after that.
int size;
cin >> size;
int dynamicArray[size];
Static Array :
Static arrays are allocated memory at compile time.
Size is fixed.
Located in stack memory space.
Eg. : int array[10]; //array of size 10
Dynamic Array :
Memory is allocated at run time.
Size is not fixed.
Located in Heap memory space.
Eg. : int* array = new int[10];
Yes right the static array is created at the compile time where as the dynamic array is created on the run time. Where as the difference as far is concerned with their memory locations the static are located on the stack and the dynamic are created on the heap. Everything which gets located on heap needs the memory management until and unless garbage collector as in the case of .net framework is present otherwise there is a risk of memory leak.
Static array :Efficiency. No dynamic allocation or deallocation is required.
Arrays declared in C, C++ in function including static modifier are static.
Example: static int foo[5];
static array:
The memory allocation is done at the complile time and the memory is allocated in the stack memory
The size of the array is fixed.
dynamic array:
The memory allocation is done at the runtime and the memory is allocated in the heap memory
The size of the array is not fixed.
Let's state this issue with a function
if we have the static array then calling the function() will iterate all the fixed allocated components from the memory. There will be no append.
On the other hand, a dynamic array will extend the memory if we append it.
static arrary meens with giving on elements in side the array
dynamic arrary meens without giving on elements in side the array
example:
char a[10]; //static array
char a[]; //dynamic array
Related
I've always declared my arrays using this method:
bool array[256];
However, I've recently been told to declare my arrays using:
bool* array = new bool[256];
What is the difference and which is better? Honestly, I don't fully understand the second way, so an explanation on that would be helpful too.
bool array[256];
This allocates a bool array with automatic storage duration.
It will be automatically cleaned up when it goes out of scope.
In most implementations this would be allocated on the stack if it's not declared static or global.
Allocations/deallocations on the stack are computationally really cheap compared to the alternative. It also might have some advantages for data-locality but that's not something you usually have to worry about. But you might need to be careful of allocating many large arrays to avoid a stack overflow.
bool* array = new bool[256];
This allocates an array with dynamic storage duration.
You need to clean it up yourself with a call to delete[] later on. If you do not then you will leak memory.
Alternatively (as mentioned by #Fibbles) you can use smart-pointers to express the desired ownership/lifetime requirements. This will leave the responsibility of cleaning up to the smart-pointer class. Which helps a lot with guaranteeing deletion, even in cases of exceptions.
It has the advantage of being able to pass it to outer scopes and other objects without copying (RVO will avoid copying for the first case too in certain cases, but storing it as a data-member and other uses can't be optimized in the first case).
The first is allocation of memory on stack:
// inside main (or function, or non-static member of class) -> stack
int main() {
bool array[256];
}
or maybe as a static memory:
// outside main (and any function, or static member of class) -> static
bool array[256];
int main() {
}
The last is allocation of dynamic memory (in heap):
int main() {
bool* array = new bool[256];
delete[] array; // you should not forget to release memory allocated in heap
}
The advantage of dynamic memory is that it can be created with variable number of elements (not 256, but from some user input for example). But you should release it each time by yourself.
More about stack, static and heap memory and when you should use each is here: Stack, Static, and Heap in C++
The difference is static vs dynamic allocation, as previous answers have indicated. There are reasons for using one over the other. This video by Herb Sutter explains when you should use what. https://www.youtube.com/watch?v=JfmTagWcqoE It is just over 1 1/2 hours.
My preference is to use
bool array[256];
unless there's a reason to do otherwise.
Mike
In C, there is a nice construct to create a c-string with more allocated space:
char str[6] = "Hi"; // [H,i,0,0,0,0]
I thought I could do the same using (4) version of string constructor, but the reference says
The behavior is undefined if s does not point at an array of at least count elements of CharT.
So it is not safe to use
std::string("Hi", 6);
Is there any way to create such std::string without extra copies and reallocations?
Theory:
Legacy c-strings
Consider the following snippet:
int x[10];
void method() {
int y[10];
}
The first declaration, int x[10], uses static storage duration, defined by cppreference as: "The storage for the object is allocated when the program begins and deallocated when the program ends. Only one instance of the object exists. All objects declared at namespace scope (including global namespace) have this storage duration, plus those declared with static or extern."
In this case, the allocation happens when the program begins and freed when it ends. From cppreference.com:
static storage duration. The storage for the object is allocated when the program begins and deallocated when the program ends.
Informally, it is implementation-defined. But, since these strings never change they are stored in read-only memory segments (.BSS/.DATA) of the executable and are only referenced during run-time.
The second one, int y[10], uses automatic storage duration, defined by cppreference as: "The object is allocated at the beginning of the enclosing code block and deallocated at the end. All local objects have this storage duration, except those declared static, extern or thread_local."
In this case, there is a very simple allocation, a simple as moving the stack pointer in most cases.
std::string
A std::string on the other hand is a run-time creature, and it has to allocate some run-time memory:
For smaller strings, std::string has an inner buffer with a constant size and is capable of storing small strings (think of it as a char buffer[N] member)
For larger strings, it performs dynamic allocations.
Practice
You could use reserve(). This method makes sure that the underlying buffer can hold at least N charT's.
Option 1: First reserve, then append
std::string str;
str.reserve(6);
str.append("Hi");
Option 2: First construct, then reserve
std::string str("Hi");
str.reserve(6);
To ensure at most one runtime allocation, you could write:
std::string str("Hi\0\0\0", 6);
str.resize(2);
However, in practice many string implementations use the Small String Optimization, which makes no allocations if the string is "short" (up to size 16 is suggested on that thread). So actually you would not suffer a reallocation by starting the string off at size 2 and later increasing to 6.
I'm dabbling around with C++ and trying to wrap my head around the pointer thing. When creating an array of objects, is it better to create the array of the object type or of pointers?
For instance:
Block grid[size]; or Block* grid[size];
From what I've been reading I was under the impression that when using objects it's almost always better to use pointers to save memory? Eventually I'm going to create a dynamically allocated 2D array of these objects, and I'm wondering if it's worth hassling to try and store them as pointers in the multidimensional array.
NOTE: I have been told to look into 2D vectors, when it comes to dynamically creating them and allocating them I'm struggling just as much as with these arrays.
Thanks in advance!
I think you are mixing something. A classic C-array is a pointer pointing to the first element. What you think of are classes which are expensive when they get (deep-)copied while calling a function or similar. These expensive function arguments (strings, vectors, and similar) are better be passed as references (or pointers).
'Modern C++' provides you with enough utility that you shouldnt use any allocation on your own, if you are not writing your own containers. You usually use pointers to point to things, that you do not own in a context. I also recommend to not use classic C-arrays anymore. Use
array<Block, size> grid; // compile-time constant size
instead of
Block grid[size]; // compile-time constant size
array<> will try to be on the stack. If size is not known to compile time, you have to allocate the memory on the heap. The STL calls these heap-arrays vector instead
vector<Block> grid(size); // runtime variable size
if (grid.size() > 0)
cout << grid[0]; // use grid like an array
The old C-style way for heap arrays was to allocate memory manually and free it after you do not need it anymore. This is very error-prone and should be avoided unless you know what you do.
As mentioned the difference to plain old arrays (which are pointers) is when calling a function. Before you had to pass a pointer and potentially the size of the array
void fancy_old_function(Block* grid, size_t size) // BAD practise
{
// do things
}
// ...
{
Block grid[size];
fancy_old_function(grid, size); // error prone
...
// maybe alot later
fancy_old_function(grid, 13); // ohoh! 13 < size?
}
In C++ and with big objects you should pass these as a reference (or make it a pointer) otherwise your vector gets deep copied.
void fancy_new_function(vector<Block>& grid) // GOOD
{
// do fancy stuff an potentially change grid
}
The drawback is now, that we have different signatures for dynamic and static arrays:
template <size_t N>
void fancy_new_function(array<Block, N>& grid) // GOOD
{
// do fancy stuff an potentially change grid
}
A huge improvement to classic C-arrays is, that we know the size of an array implicitly at all times.
You can call your fancy_new_function like this:
{
array<Block,size> grid1;
fancy_new_function(grid1); // size is implicitly deduced
// or use grid1.size();
vector<Block> grid2(size);
fancy_new_function(grid2); // developer can use grid2.size()
}
HTH
I would use Block grid[size], because why would you create an array of pointers (the only reason I can think of is for an array with unknown size at compile time) In terms of memory, the pointers are a bit more expensive, because their address and their content is stored (on the stack and on the heap respectively). And you can't forget to deallocate them when you are done with them, otherwise you will get a memory leak.
The better alternative would be std::array<Block, size> grid, or even std::vector<Block> grid.
std::vector is like an std::array, but its dynamic, without a fixed size (so you can change it a runtime, for example).
Assuming this is in a function, it doesn't 'save' memory.
One implementation uses more stack memory.
The other uses less stack memory, but uses more heap.
This entirely uses the stack:
Block grid[size];
This uses the stack to store your pointers to objects.
The memory used to store the objects is the heap:
Block* grid[size];
However, if these are global declarations, then yes, this:
Block grid[size];
does potentially waste memory because it is allocated for the lifetime of your application, and cannot be deallocated/resized.
The answer to "better" depends upon how you would the array.
If Block is small (2-8 bytes) or you need to use every element of grid, you'd be better off doing
Block grid [size] ;
In almost all cases.
Suppose sizeof (Block) > 512 and you do not use all the elements of grid and
const int size = 10 ;
you'd probably be better off with
Block grid [size] ;
Would probably make the most sense. On the other hand, suppose
const in size = 2000000 ;
then
Block *grid [size] ;
makes more sense.
Better is rather a matter of taste :-)
An array of objects may be simpler to use for simple use cases because you create and destroy the full array at once. It look a little more C++ idiomatic.
The exception I can think would be:
performance reasons with expensive to create objects. Here you only create an array for pointers with the maximum size and create objects when you need them
polymorphism with derived classes. IMHO this is the best use case for using arrays of pointers. Because if you try to copy a derived object into its base class, you will get object slicing: the base class copy will loose all attributes that are only present in derived class. So in that case, you create an array to pointers to the base class (it can even be abstract) and populate it with concrete implementations. And you can manipulate any object in the array with the virtual methods from the base class.
I have a C++ global multidimensional array with static linkage. I am assuming it will be stack allocated (I can't find the relevant section in the standard). Is it allocated contiguously?
Another question:
I want to convert these static global n-dim arrays to be allocated on heap. What is the easiest way considering I want to minimize code changes? I can think of converting the arrays to n-dim pointers and malloc'ing at the start of main and free'ing before exiting main. But I have to worry about the contiguous allocation. Anybody see a better way?
Thanks,
Nilesh.
I have a C++ global multidimensional array with static linkage. I am assuming it will be stack allocated (I can't find the relevant section in the standard).
It will not be on the stack; it will be in the global area. Globals and static-storage objects get their own region of memory that is not part of the heap nor the stack.
Further, stack (the standard calls it "automatic" storage) objects only last as long as the function call they're part of; globals are initialized before main() is called and destroyed after main() exits.
Is it allocated contiguously?
It could be, though I doubt the standard requires it. (Clarification: contiguous storage for a 1-D array is guaranteed, but there's no guarantee there aren't "gaps" between rows in 2-D and up arrays.) If you require contiguous allocation, declare the global array as a one-dimensional vector and use an inline function to convert multiple dimensions to the corresponding index. It's the same as what the compiler would have generated if contiguous storage were guaranteed.
I want to convert these static global n-dim arrays to be allocated on heap. What is the easiest way considering I want to minimize code changes?
Change the global declaration from being an array to a pointer. In this case, vectorizing the storage is strongly recommended. (No, I'm not talking about std::vector, I'm talking about reshaping into a 1-D vector.)
I can think of converting the arrays to n-dim pointers
No such beast. Closes thing is a pointer to an array of pointers, which then point to either vectors or arrays of more pointers, depth determined by number of dimensions. It would be a bear to set up, and also much slower than, the 1-d vector case above with a function to convert N-D coordinates to a 1-D index.
malloc'ing at the start of main and free'ing before exiting main.
This, except you don't have to free at the end unless you're using valgrind or similar to look for memory leaks. The OS frees all your allocations that aren't shared memory upon process exit.
So you get something like:
#include <stddef.h>
static const size_t kDimX = 5;
static const size_t kDimY = 20;
static const size_t kDimZ = 4;
inline size_t DimsToVector(size_t x, size_t y, size_t z)
{
return (x * kDimY + y) * kDimZ + z;
}
float* data = 0;
int main()
{
data = new float[kDimX * kDimY * kDimZ];
// Read elements with: data[DimsToVector(x, y, z)]
// Write v with: data[DimsToVector(x, y, z)] = k;
delete[] data; // Optional.
}
There are fancier ways, probably one in Boost, which define classes and override operator [] to hide some of the ugly, but this is about the minimum to get you going.
It's not allocated on the stack. Global variables are "allocated" in a special memory segment.
As of making your multidimensional array "contiguous", the simplest surefire way I can think of without fighting too much against the type system is to make a typedef of the lower dimension and make a pointer to that type.
typedef int TenIntegers[10];
TenIntegers* ints;
int main()
{
ints = new TenIntegers[50];
// your code here
ints[0][5] = 3;
delete[] ints;
}
1) The memory for globals is allocated somewhere "in memory". It is neither on the stack, nor on the heap. For instance, global constants are usually placed in read-only section of the executable. Strictly speaking, it's implementation dependent. Why do you need to know this?
2) Memory will be continuous.
This has been troubling me for a while. It goes to the heart of my (lack of) understanding of the difference between static and dynamic memory allocation. The following array is an ordinary static array, which should mean the memory is allocated during compile time, correct? Yet, I've set it up so that the user enters the array size at runtime.
#include <iostream>
using namespace std;
int main() {
cout << "how many elements should the array hold? ";
int arraySize;
cin >> arraySize;
int arr[arraySize];
for (int i = 0; i < arraySize; ++i)
arr[i] = i * 2;
return 0;
}
Note that there are no new or delete operators in this program. It works fine in Xcode 4.2 (default Clang compiler) as well as my school's UNIX server (GCC 4.4.5). How does the compiler know how much memory to allocate for arr when the array is created at compile time? Is this just a fluke of my compiler, dangerous code that could corrupt other memory, or is this legit?
This is a non-standard extension of your C++ compilers. Note that in C, unlike in C++, this is officially supported (i.e. standard-mandated behaviour) since C99. In C++, it is not supported because there's already a solution to the problem: Use std::vector instead of the array.
Not however that the array is not using static memory allocation (nor dynamic memory allocation), but automatic memory allocation. Automatic variables are automatically deallocated at the end of the function (the memory area where they are allocated is known as the stack, because the allocations and deallocations on it have stack semantics). To have the array use static memory allocation you would have to put static in front of the definition (note that variables in global or namespace scope always use static memory allocation, though). However, if you make the variable static, you'll find that the compiler doesn't allow to use a non-constant array size any more.
Note that std::vector stores its data with dynamic memory allocations instead. For that reason, you can also use a non-constant size even for static std::vectors.
For an array (or any object) declared inside a function, the memory is allocated on entry to the function (typically on the stack) and deallocated when the function returns. The fact that the function happens to be main in this case doesn't affect that.
This:
cin >> arraySize;
int arr[arraySize];
is a "variable-length array" (VLA). The thing is, C++ doesn't support VLAs. C does, starting with the 1999 ISO C standard (C99), but it's not a feature that C++ has adopted.
Your compiler supports VLAs in C++ as an extension. Using them makes your code non-portable.
(One problem with VLAs is that there's no mechanism for detecting an allocation failure; if arraySize is too big, the program's behavior is undefined).
For gcc, compiling with -pedantic will produce a warning:
warning: ISO C++ forbids variable length array ‘arr’
The generated code allocates arraySize bytes on the stack at runtime. Once the function returns, the stack unwinds, including "giving back" the bytes which were allocated on it for the array.
Using new and delete is for allocating space on the heap. The allocated memory lifetime on the heap is independent of any function or method scope - If you allocate space on it in a function, and the function returns, the memory is still allocated and valid.
It's a Variable Length Array (supported only in C99 and not in C++). It is allocated on the stack at runtime.