What is the difference between the following two types of array?
int array1[10];
int* array2 = new int[10];
The main difference is that a dynamic array is created on the heap. A dynamic array's size can be determined at runtime.
The difference in the below:
int x = 10;
int array1[10];
int *array2 = new char[x];
Is that array2 is pointing to the first element of an array and not the actual full array.
Note:
assert(sizeof(array1) == 40);
assert(sizeof(array2) == 4);
Memory on the heap that is created with new should eventually be destroyed using delete.
Since array2 is created on the heap, and is an array you will need to delete it with delete[] though.
Note: You can actually create a pointer to a full array and not just the first element:
int array1[10];
int *pointerToFirstElement = array1;
int (*pointerToFullArray)[10] = &array1;
int sizeOfFirstPointer = sizeof(pointerToFirstElement);
int sizeOfSecondPointer = sizeof(pointerToFullArray);
assert(sizeOfFirstPointer == sizeOfSecondPointer);//==4 since both are pointers
However what they point to have different sizes:
int sizeOfFirst = sizeof(*pointerToFirstElement);
int sizeOfSecond = sizeof(*pointerToFullArray);
assert(*sizeOfFirst == 4);
assert(*sizeOfSecond == 40);
A dynamic array is created from heap memory at run time and can be dynamically resized/freed as necessary with the new/delete keywords. An array is statically defined at compile time and will -always- take that amount of memory at all times.
Related
int *arr = new int(10);
int *arr = new int[10];
It is the code of dynamic memory allocation in c++.
But I am not getting What is the difference between these two.
For a simple example, let's talk about what happens on the stack.
int x(10)
This generally means assigning an value to an int named x.
int x[10]
This generally means creating an array named x of 10 elements.
So, when it come to dynamic memory, it's the same thing.
int* x=new int(10)
This creates a single integer on the heap and assigns it the value 10.
int* x=new int[10]
This creates an array of 10 integers on the heap.
int *arr = new int(10); allocates heap memory for a single integer, initialized to 10.
int *arr = new int[10]; allocates heap memory for an array of 10 integers, none of which are initialized to any specific value.
Keep it in mind: The ( ) and { } mainly used for initialization in declarations. And [ ] is mainly an indexing operator. So in the first statement, you are trying to allocate an int memory with 10 as the initial value. And in the second statement, you are trying to allocate a 10 int block array with no default initialization.
I've been trying to give an array its size through a variable, but it's not working because "must have a constant value".
int processes[] = { 1, 2, 3 };
int n = sizeof processes / sizeof processes[0];
...
findavgTime(processes, n);
-------------------------------------------------
void findavgTime(int processes[], int n, int bt[])
{
int wt[n], tat[n]; //These two vars are giving me the error
}
Am I missing something?
As you've seen, you can declare an array with a non-constant size like this. You could, however allocate it dynamically using new:
int* wt = new int[n];
int* tat = new int[n];
Just don't forget that you need to delete[] these arrays when you're done.
You can allocate it on the heap like how Mureinik said, but you can also allocate it on the stack (as you were trying to do) with alloca() like this:
int* wt = (int*)alloca(n * sizeof(int));
int* tat = (int*)alloca(n * sizeof(int));
free() should not be called as it is allocated on the stack, not the heap.
Some say using alloca() is bad practice because if the call causes a stack overflow, program behavior is undefined. This shouldn't be a problem as long as the array isn't too long.
If i want to give a value to int *num2, how would i do this ?
#include <stdio.h>
int main(int argc, const char * argv[]) {
// insert code here...
struct az {
int num1;
int *num2;
};
struct az test;
test.num1 =20;
printf("\n %d",test.num1);
return 0;
}
int *num2; is a pointer to some place in the memory that contains an int value. Since you just declare a pointer without any memory allocating, it is simply points to nothing (or random place).
You have to allocate memory then assign a value to this memory:
test.num2 =new int(20);
However, do not forget to delete this allocated memory when you finish:
delete test.num2;
The real question here, do you really want that pointer here? probably not.
You can assign num2 in the same way as num1. Of course, since it's not an int but an int*, you can't assign 20 to it - you can assign the address of some int variable instead:
struct az {
int num1;
int *num2;
};
struct az test;
test.num1 = 20;
int i;
test.num2 = &i;
To assign a value to the integer that test.num2 points to, you must de-reference the pointer with an asterisk, like so:
test.num2 = new int(20); // Allocates memory and sets the pointer to this memory
*(test.num2) = 10; // Assign a value of 10 to the int that test.num2 points to
To assign an address to the pointer, you must either assign another pointer to it, or assign it's value by referencing an int with an ampersand:
test.num2 = new int(20); // Allocates memory and sets the pointer to this location
int *ptr = new int(10);
delete test.num2; // Free memory that test.num2 pointed to
test.num2 = ptr // Makes test.num2 point to the same int as ptr
int x = 10;
test.num2 = &x; // Makes test.num2 point to x
In your example num2 is typically used as a pointer to a dynamically allocated array. However, neither num2 nor num1 is a good name in this case. Let's instead declare our dynamic array type as a record with the fields length and items:
struct Array {
int length;
int *items;
};
typedef struct Array Array;
If we have a variable a of type Array, before we can assign values to its elements we must first allocate memory for the array. In C this is typically done with the function malloc. This function, however, is rather error prone to use so it's a good idea to define a macro function which simplifies memory allocation:
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof (ptr)[0])
After having called NEW_ARRAY we can assign values to the array:
int length;
Array a;
length = 20;
a.length = length;
NEW_ARRAY(a.items, length);
a.items[0] = 37;
a.items[1] = 19;
...
When we are done with the array we can release the memory used by the elements:
free(a.items);
Say I have this:
int x;
int x = (State Determined By Program);
const char * pArray[(const int)x]; // ??
How would I initialize pArray before using it?
Because the initial size of the Array is determined by user input
Thanks!
Size of dynamically created array on the stack must be known at compile time.
You can either use new:
const char* pArray = new char[x];
...
delete[] pArray;
or better to use std::vector instead (no need to do memory management manually):
vector<char> pArray;
...
pArray.resize(x);
You cannot initialize an array at compile-time if you are determining the size at run-time.
But depending on what you are trying to do, a non-const pointer to const data may provide you with what you're going for.
const char * pArray = new const char[determine_size()];
A more complete example:
int determine_size()
{
return 5;
}
const char * const allocate_a( int size )
{
char * data = new char[size];
for( int i=0; i<size; ++i )
data[i] = 'a';
return data;
}
int main()
{
const char * const pArray = allocate_a(determine_size());
//const char * const pArray = new char[determine_size()];
pArray[0] = 'b'; // compile error: read-only variable is not assignable
pArray = 0 ; // compile error: read-only variable is not assignable
delete[] pArray;
return 0;
}
I do agree with others that a std::vector is probably more what you're looking for. If you want it to behave more like your const array, you can assign it to a const reference.
#include <vector>
int main()
{
std::vector<char> data;
data.resize(5);
const std::vector<char> & pArray = data;
pArray[0] = 'b'; // compile error: read-only variable is not assignable
}
The example you provided attempts to build the array on the stack.
const char pArray[x];
However, you cannot dynamically create objects on the stack. These types of items must be known at compile time. If this is a variable based on user input then you must create the array in heap memory with the new keyword.
const char* pArray = new char[x];
However, not all items need to be created on the heap. Heap allocation is normally a lot slower then stack allocation. If you want to keep your array on the stack you could always use block based initialization.
#define MAX_ITEMS 100
const char pArray[MAX_ITEMS]
It should be noted that the second option is wasteful. Because you can not dynamically resize this array you must allocate a large enough chunk to hold the maximum number of items your program could create.
Finally, you can always use data structures provide by C++. std::vector is such a class. It provides you a good level of abstraction and item are stored in contingent memory like an array. As noted by one of the other answers you should use the resize option once you know the final size of your vector.
std::vector<char> pArray;
pArray.resize(X);
The reason for this is every time you add an element to a vector, if it no longer has enough room to grow, it has to relocate all items so they can exist next to one another. Using the resize method helps prevent vector from having to grow as you add items.
I'm trying to get this clear up in my mind.
int* arrayA = new int[3];
int arrayB[3] = {1,2,3}
arrayA = arrayB;
Does the value of arrayB get copied over to arrayA?
Or does arrayA become a pointer to arrayB?
Naked new is evil, especially for arrays. Use std::vector if you need dynamic array and std::array if you need static one.1
Now the actual answer is simple. arrayA is a pointer. So it's made to point to arrayB. That has additional effect that:
you now leaked the allocated pointer.
attempt to delete arrayA will now crash or something else unpleasant, because you would be trying to free unallocated memory.
Actually while C++ allows assigning structures and classes, it does not support assigning arrays at all. Unless part of an object either managed as in std::vector or as array member as in std::array (note: std::array is C++11).
1 The main reason is that the containers guarantee the resources will be released in their destructors, so called RAII idiom, avoiding most opportunities for memory leaks and dangling references.
int* arrayA = new int[3];
arrayA now stores the address in memory of a different memory block thats large enough to contain 3 ints which is stored on the heap.
int arrayB[3] = {1,2,3};
arrayB is a block of memory thats large enough to contain 3 ints which is stored on the stack.
arrayA = arrayB;
Copies the address of the memory block that's stored on the stack into the variable arrayA. You have now lost the only reference to memory block stored on the heap, and have no way to free up the memory (a memory leak)
The memory stored on the stack and now pointed to by arrayA will not be safe to access when the current function returns. In particular returning arrayA (or arrayB) is not safe.
For
Does the value of arrayB get copied over to arrayA?
Nope. It will not copy arrayB to arrayA. If you want to do so, you can do like,
for (int i=0;i<3;i++) arrayA[i]=arrayB[i]; //This is two arrays has same value
does arrayA become a pointer to arrayB?
Yes. It become a pointer to array of arrayB. After arrayA = arrayB; statement, memory allocated in the first line can not be accessible and it is a leak.
arrayA=arrayB; result in copying the address of arrayB to arrayA. arrayA will start pointing to the arrayB. Check it using,
printf("\n Base address of A[%u] base address of B[%u]", arrayA, arrayB);
Hope this helps.
Array name represents the base address of the array.
arrayA=arrayB;
stores the base address of arrayB to arrayA. The further values can be accessed by incrementing the pointer arrayA.
i.e
*(arrayA) value is 1
*(arrayA+1) value is 2
*(arrayA+2) value is 3
The memory created should be freed at the last using
delete[] arrayA
Q. Does the value of arrayB get copied over to arrayA?
Ans. NO
Or
Q. does arrayA become a pointer to arrayB?
Ans YES.
But the memory chunk which you allocated using new is lost. As no one is having the address which was starting point of that chunk.
This is vindicated by this program :
#include<iostream>
using namespace std;
const int MAX=4;
int main(){
int* arrayA = new int[MAX];
for(int i=0;i<MAX;i++){ arrayA[i]=i; }
int arrayB[MAX] = {10,20,30,40};
arrayA = arrayB;
for(int i=0; i<MAX;i++){ cout<<" a["<<i<<"] = "<<arrayA[i]<<endl; }
return 0;
}
The output of this code is :
a[0] = 10
a[1] = 20
a[2] = 30
a[3] = 40
on
g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4
which is true in general as well.
visualization of this is somewhat like this
arrayA-> [0][1][2][3]
arrayB-> [10][20][30][40]
Intially arrayA has address of [0] ( + sum extra memory on the negative indexes for size used by compiler to do the de-alloctation ).
after
arrayA=arrayB;
arrayA has address of [10];
suppose you call delete on arrayA what shall happen ??
*** Error in `./a.out': double free or corruption (out): 0x00007fff561281d0 ***
This is evident from the following code also
#include<iostream>
using namespace std;
const int MAX=4;
int main(){
int* arrayA = new int[MAX*2];
for(int i=0;i<MAX;i++){ arrayA[i]=i; }
int* arrayC = new int[MAX];
int j=0;
for(int i=MAX*100;i>=0;i-=10,j++){ arrayC[j]=i; }
arrayA = arrayC;
for(int i=0; i<MAX;i++){ cout<<" a["<<i<<"] = "<<arrayA[i]<<endl; }
delete[] arrayA;
return 0;
}
The out put is :
a[0] = 400
a[1] = 390
a[2] = 380
a[3] = 370
*** Error in `./a.out': free(): invalid next size (fast): 0x0000000002028040 ***
Aborted (core dumped)
Just pay attention to :
"invalid next size"
This clearly says about the size value written before the arrayA in the negative indexes.