I know that arrays can be created on the stack with syntax such as int array[5]; where the size must be known at compile time and array is a non modifiable l-value.
You can also create an array dynamically on the heap with new such as int* array = new int[5]; where it becomes possible to have a size of variable length and resize the array.
But what about something like:
int* array;
array[2] = 3;
cout << array[2] << endl;
Which creates an array on the stack that appears to be resizable because I can continue adding elements. The only other thing that should be kept track of is the size.
I wrote the above code accidentally in a project and I haven't seen it used ever. I not sure if it should be used at all, but I'm also not sure what's incorrect about it.
But what about something like:
int* array;
array[2] = 3;
cout << array[2] << endl;
Which creates an array on the stack that appears to be resizable because I can continue adding elements. The only other thing that should be kept track of is the size.
Nope. Unfortunately, C++ doesn't work like that. You need to allocate the array with new if you want to create a dynamic array with raw pointers.
This is because pointers only hold addresses. They don't actually guarantee that there is memory allocated at that address. Thus, you will need to allocate memory at an address if you want to use it.
If you want a dynamically allocated memory, you have other options including using std::vector, or std::unique_ptr, or std::shared_ptr. You can find more information on this and some examples at this question.
Writing int *array; does not create an array, it declares a pointer to some random memory page, and if you try to dereference this pointer, your program will receive “Segmentation fault” signal and will be shut down. Never use pointers without their proper initialization using addresses of existing objects, or allocated objects (using new), or functions/methods which return valid address.
Related
This question is similar to Problem with delete[], how to partially delete the memory?
I understand that deleting an array after incrementing its pointer is not possible as it loses the track of how many bytes to clean. But, I am not able to understand why one-by-one delete/deallocation of a dynamic array doesn't work either.
int main()
{
int n = 5;
int *p = new int[n];
for(int i=0;i<n;++i){
delete &p[i];
}
}
I believe this should work, but in clang 12.0 it fails with the invalid pointer error. Can anyone explain why?
An array is a contiguous object in memory of a specific size. It is one object where you can place your data in and therefore you can only free/delete it as one object.
You are thinking that an array is a list of multiple objects, but that's not true. That would be true for something like a linked list, where you allocate individual objects and link them together.
You allocated one object of the type int[n] (one extent of memory for an array) using the operator new
int *p = new int[n];
Elements of the array were not allocated dynamically separately.
So to delete it you just need to write
delete []p;
If for example you allocated an array of pointers like
int **p = new int *[n];
and then for each pointer of the array you allocated an object of the type int like
for ( int i = 0;i < n;++i )
{
p[i] = new int( i );
}
then to delete all the allocated objects you need to write
for ( int i = 0; i < n; ++i )
{
delete p[i];
}
delete []p;
That is the number of calling of the operator delete or delete [] one to one corresponds to the number of calling operator new or new [].
One new always goes with one delete. Just as that.
In detail, when we request an array using new, what we actually do is to get a pointer that controls a contiguous & fixed block on the memory. Whatever we do with that array, we do it through that pointer and this pointer associates strictly with the array itself.
Furthermore, let's assume that you were able to delete an elemnent in the middle of that array. After the deletion, that array would fall apart and they are not contiguous anymore! By then, an array would not really be an array!
Because of that, we can not 'chop off' an array into separate pieces. We must always treat an array as one thing, not distinctive elements scattered around the memory.
Greatly simplyfyinh: in most systems memory is allocated in logical blocks which are described by the starting pointer of the allocated block.
So if you allocate an array:
int* array = new int[100];
OS stores the information of that allocation as a pair (simplifying) (block_begin, size) -> (value of array ptr, 100)
Thus when you deallocate the memory you don't need to specify how much memory you allocated i.e:
// you use
delete[] array; // won't go into detail why you do delete[] instead of delete - mostly it is due to C++ way of handling destruction of objects
// instead of
delete[100] array;
In fact in bare C you would do this with:
int* array = malloc(100 * sizeof(int))
[...]
free(array)
So in most OS'es it is not possible due to the way they are implemented.
However theoretically allocating large chunk of memory in fact allocate many smaller blocks which could be deallocated this way, but still it would deallocate smaller blocks at a time not one-by-one.
All of new or new[] and even C's malloc do exactly the same in respect to memory: requesting a fix block of memory from the operating system.
You cannot split up this block of memory and return it partially to the operating system, that's simply not supported, thus you cannot delete a single element from the array either. Only all or none…
If you need to remove an element from an array all you can do is copy the subsequent elements one position towards front, overwriting the element to delete and additionally remember how many elements actually are valid – the elements at the end of the array stay alive!
If these need to be destructed immediately you might call the destructor explicitly – and then assure that it isn't called again on an already destructed element when delete[]ing the array (otherwise undefined behaviour!) – ending in not calling new[] and delete[] at all but instead malloc, placement new for each element, std::launder any pointer to any element created that way and finally explicitly calling the constructor when needed.
Sounds like much of a hassle, doesn't it? Well, there's std::vector doing all this stuff for you! You should this one it instead…
Side note: You could get similar behaviour if you use an array of pointers; you then can – and need to – maintain (i.e. control its lifetime) each object individually. Further disadvantages are an additional level of pointer indirection whenever you access the array members and the array members indeed being scattered around the memory (though this can turn into an advantage if you need to move objects around your array and copying/moving objects is expensive – still you would to prefer a std::vector, of pointers this time, though; insertions, deletions and managing the pointer array itself, among others, get much safer and much less complicated).
This question already has answers here:
Dynamically allocating an array of objects
(7 answers)
Closed 8 years ago.
Im learning at the moment c++ with a book.
I have many problems with the pointers...
int i;
cin >> i;
const int *quantity = &i;
int array[*quantity];
Is that correct? Can i control now the size of the array during the programm is running?
That's very nearly correct, except that the size of the array (which you've attempted to allocate on the stack here) has to be known at compile time, so no you can't do this.
However, you can allocate an array at runtime using new[], which will let you pass in a size that's not a compile time constant (new allocates on the heap):
int* array = new int[*quantity];
// ...
delete[] array; // Manual allocations with `new` require manual deallocations
Note that in your particular code example, there's no need to play with pointers at all -- you can just use i directly:
int* array = new int[i];
No, this is incorrect. Array size must be a constant expression, which means that it can be evaluated during compilation, and this is not the case for your code.
If you want arrays of different sizes, you can use dynamic allocation:
int* array = new int[i];
Or much better use std::vector:
std::vector<int> array(i);
Arrays are a fixed size in memory. Because arrays also represent a contiguous block of objects in memory, by definition the same array cannot change size in memory, because it would then need to move memory that may not even belong to the same application.
There are ways to move your array, however, copying it to a new array with more space when it gets full, and there are more mutable types such as std::Vector, but an array as deifned here cannot ever change size.
What this code would instead do is
place a value in i
Place a value in quantity representing the address (pointer) of i
Create a new array using the value in the address quantity
Note that pointers are addresses, specifically saying the byte address in RAM of a given variable (try printing a pointer directly, for example!). The * and & operators quickly say "get value at address" and "get address of"
I'm familiar with Java and trying to teach myself C/C++. I'm stealing some curriculum from a class that is hosting their materials here. I unfortunately can't ask the teacher since I'm not in the class. My concern is with the section under "dynamically declared arrays":
If you
want to be able to alter the size of
your array at run time, then declare
dynamic arrays. These are done with
pointers and the new operator. For the
basics on pointers, read the pointers
section.
Allocate memory using new, and then
you access the array in the same way
you would a static array. For example,
int* arrayPtr = new int[10]; for
(int i = 0; i < 10; i++) {
arrayPtr[i] = i; }
The memory picture is identical to the
static array, but you can change the
size if you need to. Don't forget you
must deallocate the memory before
allocating new memory (or you will
have a memory leak).
delete [] arrayPtr; // the []
is needed when deleting array pointers
arrayPtr = new int[50]; . . .
When you're completely done with the
array, you must delete its memory:
delete [] arrayPtr;
Dynamic multi-dimensional arrays are
done in a similar manner to Java. You
will have pointers to pointers. For an
example, see a
My understanding is that an array in C is simply a reference to the memory address of the first element in the array.
So, what is the difference between int *pointerArray = new int[10]; and int array[10]; if any?
I've done some tests that seem to indicate that they do the exact same thing. Is the website wrong or did I read that wrong?
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char** argv) {
// Initialize the pointer array
int *pointerArray = new int[10];
for (int i = 0; i < 10; i++){
pointerArray[i] = i;
}
// Initialize the regular array
int array[10];
for (int i = 0; i < 10; i++){
array[i]= i;
}
cout << *(pointerArray + 5) << endl;
cout << *(array + 5) << endl;
cout << pointerArray[5] << endl;
cout << array[5] << endl;
cout << pointerArray << endl;
cout << array << endl;
return 0;
}
Output:
5
5
5
5
0x8f94030
0xbfa6a37c
I've tried to "dynamically re-size" my pointer array as described on the site, but my new (bigger) pointer array ends up filled with 0's which is not very useful.
int array[10]; declares the array size statically, that means it is fixed - which is the only major difference. It also might be allocated to be inside the function's stack frame, i.e. on the program's stack. You do not need to worry about using delete [] on that kind of array, in fact, you might crash the program if you delete it.
When you use operator new, you allocate memory dynamically which could be slower and the memory usually comes from the heap rather than the program's stack (though not always). This is better in most cases, as you are more limited in the stack space than the heap space. However, you must watch out for memory leaks and delete[] your stuff when you don't need it anymore.
As to your array being filled with zeros, what your class material does not say is that you have to do this:
int *arr = new int[20]; // old array
//do magic here and decide that we need a bigger array
int *bigger = new int[50]; // allocate a bigger array
for (int i = 0; i < 20; i++) bigger[i] = arr[i]; // copy the elements from the old array into the new array
delete[] arr;
arr = bigger;
That code extends the array arr by 30 more elements. Note that you must copy the old data into the new array, or else it will not be there (in your case, everything becomes 0).
My understanding is that an array in C is simply a reference to the memory address of the first element in the array.
So, what is the difference between int *pointerArray = new int[10]; and int array[10]; if any?
What you mention is the reason for much confusion in any C/C++ beginner.
In C/C++, an array corresponds to a block of memory sufficiently large to hold all of its elements. This is associated to the [] syntax, like in your example:
int array[10];
One feature of C/C++ is that you can refer to an array by using a pointer to its type. For this reason, you are allowed to write:
int* array_pointer = array;
which is the same as:
int* array_pointer = &array[0];
and this allows to access array elements in the usual way: array_pointer[3],
but you cannot treat array as a pointer, like doing pointer arithmetics on it (i.e., array++ miserably fails).
That said, it is also true that you can manage arrays without using the [] syntax at all and just allocate arrays by using malloc and then using them with raw pointers. This makes the "beauty" of C/C++.
Resuming: a distinction must be made between the pointer and the memory that it points to (the actual array):
the [] syntax in declarations (i.e., int array[10];) refers to both aspects at once (it gives you, as to say, a pointer and an array);
when declaring a pointer variable (i.e., int* p;), you just get the pointer;
when evaluating an expression (i.e., int i = p[4];, or array[4];), the [] just means dereferencing a pointer.
Apart from this, the only difference between int *pointerArray = new int[10]; and int array[10]; is that former is allocated dynamically, the latter on the stack.
Dynamically allocated:
int * pointerArray = new int[10];
[BTW, this is a pointer to an array of 10 ints, NOT a pointer array]
Statically allocated (possibly on the stack):
int array[10];
Otherwise they are the same.
The problem with understanding C/C++ arrays when coming from Java is that C/C++ distinguishes between the array variable and the memory used to store the array contents. Both concepts are important and distinct. In Java, you really just have a reference to an object that is an array.
You also need to understand that C/C++ has two ways of allocating memory. Memory can be allocated on the help or the stack. Java doesn't have this distinction.
In C and C++, an array variable is a pointer to the first element of the array. An array variable can exist on the heap or the stack, and so can the memory that contains its contents. And they can be difference. Your examples are int arrays, so you can consider the array variable to be an int*.
There are two differences between int *pointerArray = new int[10]; and int array[10];:
The first difference is that the memory that contains the contents of the first array is allocated on the heap. The second array is more tricky. If array is a local variable in a function then its contents are allocated on the stack, but if it is a member variable of a class then its contents are allocated wherever the containing object is allocated (heap or stack).
The second difference is that, as you've realised, the first array is dynamic: its size can be determined at run-time. The second array is fixed: the compiler must be able to determine its size at compile time.
First, I'd look for some other place to learn C++. The page you cite is
very confusing, and has little to do with the way one actually programs
in C++. In C++, most of the time, you'd use std::vector for an array,
not the complex solutions proposed on the page you cite. In practice,
you never use operator new[] (an array new).
In fact, std::vector is in some ways more like ArrayList than simple
arrays in Java; unlike an array in Java, you can simply grow the vector
by inserting elements into it, preferrably at the end. And it supports
iterators, although C++ iterators are considerably different than Java
iterators. On the other hand, you can access it using the []
operator, like a normal array.
The arrays described on the page you cite are usually called C style
arrays. In C++, their use is mostly limited to objects with static
lifetime, although they do occasionally appear in classes. In any case, they are never allocated dynamically.
The main difference is that some operations that are allowed on pointers are not allowed on arrays.
On the one hand:
int ar[10];
is using memory allocated on the stack. You can think of it also locally available and while it is possible to pass a pointer / reference to otehr functions, the memory will be freed as soon as it goes out of scope (in your example at the end of the main method but that's usually not the case).
On the other hand:
int ar* = new int[10];
allocates the memory for the array on the heap. It is available until your whole program exits or it is deleted using
delete[] ar;
note, that for delete you need the "[]" if and only if the corresponding new has had them, too.
There is a difference but not in the area that you point to. *pointerArray will point to the beginning of a block of memory of size 10 bytes. So will array. The only difference will be where it is stored in memory. pointerArray is dynamically assigned memory (at run-time) and hence will go on the heap, while array[10] will be allocated at compile-time and will go to the stack.
It is true that you can get most of array functionality by using a pointer to its first element. But compiler knows that a static array is composed of several elements and the most notable difference is the result of the sizeof operator.
sizeof(pointerArray) = sizeof int*
sizeof(array) = 10 * sizeof int
I come from a java background and there's something I could do in Java that I need to do in C++, but I'm not sure how to do it.
I need to declare an array, but at the moment I don't know the size. Once I know the size, then I set the size of the array. I java I would just do something like:
int [] array;
then
array = new int[someSize];
How do I do this in C++?
you want to use std::vector in most cases.
std::vector<int> array;
array.resize(someSize);
But if you insist on using new, then you have do to a bit more work than you do in Java.
int *array;
array = new int[someSize];
// then, later when you're done with array
delete [] array;
No c++ runtimes come with garbage collection by default, so the delete[] is required to avoid leaking memory. You can get the best of both worlds using a smart pointer type, but really, just use std::vector.
In C++ you can do:
int *array; // declare a pointer of type int.
array = new int[someSize]; // dynamically allocate memory using new
and once you are done using the memory..de-allocate it using delete as:
delete[]array;
Best way would be for you to use a std::vector. It does all you want and is easy to use and learn. Also, since this is C++, you should use a vector instead of an array. Here is an excellent reason as to why you should use a container class (a vector) instead of an array.
Vectors are dynamic in size and grow as you need them - just what you want.
The exact answer:
char * array = new char[64]; // 64-byte array
// New array
delete[] array;
array = new char[64];
std::vector is a much better choice in most cases, however. It does what you need without the manual delete and new commands.
As others have mentioned, std::vector is generally the way to go. The reason is that vector is very well understood, it's standardized across compilers and platforms, and above all it shields the programmer from the difficulties of manually managing memory. Moreover, vector elements are required to be allocated sequentially (i.e., vector elements A, B, C will appear in continuous memory in the same order as they were pushed into the vector). This should make the vector as cache-friendly as a regular dynamically allocated array.
While the same end result could definitely be accomplished by declaring a pointer to int and manually managing the memory, that would mean extra work:
Every time you need more memory, you must manually allocate it
You must be very careful to delete any previously allocated memory before assigning a new value to the pointer, lest you'll be stuck with huge memory leaks
Unlike std::vector, this approach is not RAII-friendly. Consider the following example:
void function()
{
int* array = new int[32];
char* somethingElse = new char[10];
// Do something useful.... No returns here, just one code path.
delete[] array;
delete[] somethingElse;
}
It looks safe and sound. But it isn't. What if, upon attempting to allocate 10 bytes for "somethingElse", the system runs out of memory? An exception of type std::bad_alloc will be thrown, which will start unwinding the stack looking for an exception handler, skipping the delete statements at the end of the function. You have a memory leak. That is but one of many reasons to avoid manually managing memory in C++. To remedy this (if you really, really want to), the Boost library provides a bunch of nice RAII wrappers, such as scoped_array and scoped_ptr.
use std::array when size is known at compile time otherwise use std::vector
#include <array>
constexpr int someSize = 10;
std::array<int, someSize> array;
or
#include <vector>
std::vector<int> array; //size = 0
array.resize(someSize); //size = someSize
Declare a pointer:
int * array;
So I have a pointer to an array of pointers. If I delete it like this:
delete [] PointerToPointers;
Will that delete all the pointed to pointers as well? If not, do I have to loop over all of the pointers and delete them as well, or is there an easier way to do it? My google-fu doesn't seem to give me any good answers to this question.
(And yeah, I know I need to use a vector. This is one of those "catch up on C++" type assignments in school.)
Yes you have to loop over the pointers, deleting individually.
Reason: What if other code had pointers to the objects in your array? The C++ compiler doesn't know if that's true or not, so you have to be explicit.
For an "easier way," two suggestions: (1) Make a subroutine for this purpose so at least you won't have to write the code more than once. (2) Use the "smart pointer" design paradigm where you hold an array of objects with reference-counters, then the objects are deleted when the objects are no longer referenced by any code.
I agree with Jason Cohen though we can be a bit clearer on the reason for needing to delete your pointers with the loop. For every "new" or dynamic memory allocation there needs to be a "delete" a memory de-allocation. Some times the "delete" can be hidden, as with smartpointers but it is still there.
int main()
{
int *pI = new int;
int *pArr = new int[10];
so far in the code we have allocated two chunks of dynamic memory. The first is just a general int the second is an array of ints.
delete pI;
delete [] pArr;
these delete statements clear the memory that was allocated by the "new"s
int ppArr = new int *[10];
for( int indx = 0; indx < 10; ++indx )
{
ppArr[indx] = new int;
}
This bit of code is doing both of the previous allocations. First we are creating space for our int in a dynamic array. We then need to loop through and allocate an int for each spot in the array.
for( int indx = 0; indx < 10; ++indx )
{
delete ppArr[indx];
}
delete [] ppArr;
Note the order that I allocated this memory and then that I de-allocated it in the reverse order. This is because if we were to do the delete [] ppArr; first we would lose the array that tells us what our other pointers are. That chunk or memory would be given back to the system and so can no longer be reliably read.
int a=0;
int b=1;
int c=2;
ppArr = new int *[3];
ppArr[0] = &a;
ppArr[1] = &b;
ppArr[2] = &c;
This I think should be mentioned as well. Just because you are working with pointers does not mean that the memory those pointers point to was dynamically allocated. That is to say just because you have a pointer doesn't mean it necessarily needs to be delete. The array I created here is dynamically allocated but the pointers point to local instances of ints When we delete this we only need to delete the array.
delete [] ppArr;
return 0;
}
In the end dynamically allocated memory can be tricky and anyway you can wrap it up safely like in a smart pointer or by using stl containers rather then your own can make your life much more pleasant.
See boost pointer container for a container that does the automatic deletion of contained pointers for you, while maintaining a syntax very close to ordinary STL containers.
Pointers are pretty much just memory references and not spiffy little self-cleaning .net objects. Creating proper destructors for each class will make the deletion a little cleaner than massive loops throughout the code.
Let's take a (pseudocoded) real world example .Imagine that you had a class like this:
class Street
{
public:
Street();
~Street();
private:
int HouseNumbers_[];
}
typedef *Street StreetSign;
If you have an array of street signs, and you delete your array of streetsigns, that doesn't mean that you automatically delete the sreets. They re still there, bricks and mortar, they just don't have those signs pointing to them any more. You have got rid of those specific instances of pointers to the streets.
An array of pointers is (conceptually) a bit like an array of integers, it's an array of numbers representing the memory locations of various objects. It isn't the objects themselves.
If you delete[] the array of pointers, all you have done is delete an array of integers.
I think you're going to have to loop over I'm afraid.
I don't know why this was answered so confusingly long.
If you delete the array of pointers, you will free
the memory used for an array of usually ints.
a pointer to an object is an integer containing the adress.
You deleted a bunch of adresses, but no objects.
delete does not care about the content of a memory space,
it calls a destructor(s) and marks the mem as free.
It does not care that it just deleted a bunch of adresses
of objects, it merely sees ints.
That's why you have to cycle through the array first! and call delete
on every element, then you can delete the storage of the array itself.
Well, now my answer got somewhat long... .... strange... ;)
Edit:
Jason's answer is not wrong, it just fails to hit the spot. Neither
the compiler nor anything else in c(++) cares about you deleting stuff that is elsewhere
pointed to. You can just do it. Other program parts trying to use the deleted objects
will segfault on you. But no one will hinder you.
Neither will it be a problem to destroy an array of pointers to objects, when the objects
are referenced elsewhere.