Assume I have an array a and an array b. Both have the same type and size but different values.
Now I create 3 or so pointers that point to different elements in a, you could say a[0], a[4] and a[13].
Now if I overwrite a with b via a=b - Where will the pointers point?
Do the pointers still point to their original positions in a but the values they point to are now those of b?
Arrays are not assignable in C++. Once you declare an array:
int a[10];
there is no way of overwriting it, only of changing the values it contains. Specifically, you can't do:
int a[10], b[10];
a = b; // cannot work in C++ (or C)
If you create the array dynamically and assign pointers:
int * a = new int[10];
int * p = a + 1;
int * b = new int[10];
a = b;
then the pointer p still points into the first array, but you have a memory leak.
In the case of a struct containing an array:
struct S {
int a[10];
};
S s1, s2;
int * p = s1.a + 1;
s1 = s2;
then the pointer p still points into the first struct's array, but the array contents will have been overwritten with the array contents from the second struct.
That's an interesting question. So lets break it down:
Where will the pointers point?
Same place as they did before. They only contain the address of the memory, nothing more. Changing "a" will not change the pointers.
Will the pointers point to their original positions in a but the values they point to are now those of b?
If a was created as
int *a = new int[34];
then no.
If you don't directly change the variables that are storing your pointers, nothing is going to change the location they point to. Changing the values stored in the "pointed to" locations will change the dereferenced values of your pointers, but they still point to the same place.
Learning how to use a good graphical debugger and stepping through a test program would help illustrate what is going on. I don't know if you are on the windows platform, but the visual studio (and I would think Visual C++ Express) debugger will show you everything you need to know so you can run your own experiment and see exactly what your code is doing.
You can not overwrite anything with a=b. Effectively this will leak memory, by leaving your whole 'a' array somewhere into the memory with no pointer to it. 'a' will point to the first element of 'b' after a=b.
After a declaration like int * a = new a[5]; , your 'a' point to the first element of the array. You can do pointer arithmetic like a++, which will then go to the second element in the array, leaving your first element with no pointer to it. The same way a=b will point it to the first element of the b array.
Your other pointers a[3], a[14] e.t.c. will still point to the same memory as before.
Note that a[0] is the same as 'a'.
You must make a difference between arrays and pointers. If you use arrays you cannot make a=b.
If you use pointers you can make a = b and that will mean that a points where b points. The values inside them will not change, but it will be impossible to access. Once you make a = b, when accessing a[3] you will access b[3], because a[3] means: "where a points + 3", and a points where b points, hence b[3].
If you don't free where a was allocated, that info is still in memory, so if you made 3 pointers that point where a used to point + some value, that info is still accessible and not modified.
a=b won't work, but you can copy array b into a using STL.
As an example :
int a[15] = {0};
int b[15] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
int *p1 = a; // pointer to a[0]
int *p2 = a+4; // pointer to a[4]
int *p3 = a+13; // pointer to a[13]
std::copy(&b[0], &b[15], a);
If you have pointers to array a elements declared before the copy :
pointers' address won't change if you copy b into a
only pointers' values
change
Related
I am working on an assignment for my c++ class where I need to dynamically assign a new int, array, and pointer from another pointer to practice dynamic memory allocation.
At first, I was struggling with creating a new int to provide an int for my new array, but I got it to compile and was wondering if my declarations were correct.
int *dmaArray = new int;
*dmaArray = 4;
I then took that and put it into a dynamically created array, but I don't know how to declare values of the array as it errors out saying "cannot convert to int". I did some thinking and I believe it's because it was declared and needs to be initialized at the declaration; I can't because the declaration is already a declaration (new) in itself.
int * nodeValues = new int[*dmaArray];
nodeValues[*dmaArray] = {6, 2, 28, 1};
A loop wouldn't work to assign values after since the values aren't consecutive or in any pattern. (well, regardless, I would need to use an array because the assignment said so.
This is not how to to declare a dynamic array and initialize it:
int * nodeValues = new int[*dmaArray];
nodeValues[*dmaArray] = {6, 2, 28, 1};
So you declare it this way:
int* nodeValues = new int[dmaArray];
And to assign values to it use loops or manually:
nodeValues[0] = 6;
nodeValues[1] = 2;
nodeValues[2] = 28,
nodeValues[3] = 1;
Remember arrays use indexes to read/write its elements as the fact being some sort of data of the same type contiguous to each other in memory.
So if you want to print the array:
for(auto i(0); i != dmaArray; ++i)
std::cout << nodeValues[i] << ", ";
Finally you should clean memory dynamically allocated after finishing with it because the compiler doesn't do it for you:
delete[] nodeValues;
I figured out how:
int * nodeValues = new int[*dmaArray]{6,5,28,1};
I'm using a convolution process using a 3x3 grid over a 2d image that is represented in a 1d array. I am iterating over certain pixels and need access to the surrounding pixels (ignoring edge cases). Is it possible to have a pointer that always points to a location next to another pointer?
int* a = new int[5];
//populate with data (0, 2, 4, 6, 8)
int* b = &a[2]; //4
int* c = b+1; //6
b++; //b->6, c->6
//What if after b++ I want c->8?
Is there any way to make a pointer relative to another pointer such that when the main pointer is changed, the other pointers change with it? So, a pointer that always points to the neighbor of another pointer.
Incrementing b does not change c. If you want both pointers to move in parallel, you must increment both of them:
b++;
c++;
This seems like more trouble than it's worth, though, since you can just do b + 1 to find the "next" element in the array.
I'll cut to the chase to save you all some boredom of surplus reading:
I've tried to comb the internet in search of tutorials over dynamical arrays of objects/classes where they explain how pointers are implemented here.
This in particular: TheClass **foo[10]; or something like that, I don't understand what two stars/asterisks are good for and how they are used.
And this whole thing in general.
I do know how dynamical arrays are declared,how regular pointers are used,how to make classes,how to make dynamic arrays of classes.
But all this combined got me confused.
So my questions are:
What does this do and how does it work?
Can you recommend a site where you know examples/tutorials of this can be found?
Does this have a specific name rather than "dynamic object arrays with double pointers"
or whatnot?
If no tutorial comes to mind, I'd appreciate it if you could make a very, very brief example.
Like for instance
int *something;
int somethingElse = 10;
something = &somethingElse; /*Now when you change "somethingElse","something"
will also change to the same number*/
A little super-short example and explanation like that would be greatly appreciated. =)
The simplest, more or less usefull, example using pointers to pointers would be a two dimensional array. So for example
//Create a pointer to (an array of) pointers to (an array of) ints
int** array2D;
//Create a array of pointers to (an array of) ints and assign it to the pointer
array2D = new int*[10];
//Assign each of the pointers to a new array of 10 ints
for(size_t i =0; i<10;i++) {
array2D[i] = new int[10];
}
//Now you have an 2 dimensional array of ints that can be access by
array2D[1][3] = 15;
int test = array2D[1][3];
I hope this explains a bit what pointers to pointers are and how they work.
A pointer is, well, a pointer. It points at something. Period. If you understand that much, then you should be able to understand what a pointer to a pointer is. It is just a pointer whose value is the memory address of another variable that is itself a pointer to something else. That's all. Every time you add a * to the mix, it is just another level of pointer indirection. For example:
int i;
int* p_i = &i; // p_i is a pointer to an int and points at i
int** pp_i = &p_i; // pp_i is a pointer to an int* and points at p_i
int*** ppp_i = &pp_i; // ppp_i is a pointer to an int** and points at pp_i
Now apply that concept to TheClass **foo[10]; (which is actually TheClass** foo[10]; from the compiler's perspective). It is declaring an array named foo that contains 10 TheClass** pointer-to-pointer elements. Each TheClass* might be a pointer to a specific TheClass object, or it might be a dynamic array of TheClass elements (no way to know without more context), then each TheClass** is a pointer to a particular TheClass* pointer.
Well i see you aim for the complete answer, i'll give u a brief example on that.
If you define an array of pointers to pointers, like in your "class foo**[10]" example, let's say:
int numX = 100;
int numY = 1000;
Node **some[10];
some[0] = new Node*[numX];
some[0][0] = new Node[numY];
Then what it does mean is:
You have 10 Node** in your 1st level. So you have 10 pointers to type Node**, but they aren't pointing anywhere useful yet.
This is just 10 adjacent memory locations for storing pointers. In this case it is irrelevant what they are pointing to, mainly it is just 10 fields containing space for a pointer.
Then take the first of these 10 "spaces" and assign the address of an array of 100 pointers to type Node*
some[0] = new Node*[numX]; //numX = 100
This is done and evaluated during runtime, so u can use a variable value given by user input or some application logic, to define dimensions of arrays aka memory-fields.
Now you have 1 of 10 pointers pointing to 100 pointers to type Node*, but still pointing to a black hole.
In the last step create 1000 objects of type Node and attach their addresses to the first of your 100 pointers.
some[0][0] = new Node[numY]; //numY = 1000
In the above example this means, only [0][0][0] to [0][0][999] are objects, the 1000 you created with:
This way you can build multi-dimensional arrays with the specified type. What makes the whole thing work, is that you instantiate what you need in the last dimension (3) and create pointers to uniquely index every field created from [0][0][0] to [9][99][999].
some[0][1]; // memory violation not defined
some[0][0]; // good -> points to a *Node
some[0][0][0]; // good -> actually points to Node (data)
some[1][0][0]; // memory violation not defined
As far as i know, most often you use a one-dimensional array and some tiny math, to simulate two-dimensional arrays. Like saying element [x][y] = [x+y*width];
However you want to use your memory, in the end it all boils down to some memory-adresses and their content.
TheClass** foo[10];
This line of code tells the compiler to a make an array called foo of 10 elements of type pointer to (pointer to Theclass ).
In general when you want to figure out a type that involve multiple astrisks, ampersands. Read Left to Right. so we can break out the code above to something like this:
( (Theclass) * ) * foo[10]
^ ^ ^ ^ ^
5 4 3 2 1
#1 an array of 10 elements named #2 foo #3 of type pointer #4 to pointer #5 to Theclass
I was thinking of ways to make an array larger quickly in C++ and I came up with this:
// set up arr1
int *arr1 = new int[5];
// add data to arr1
arr1[0] = 1;
arr1[1] = 2;
arr1[2] = 3;
arr1[3] = 4;
arr1[4] = 5;
// set up arr2
int *arr2 = new int[10];
arr2 = arr1; // assign arr1 to arr2
// add more values
arr2[5] = 6;
arr2[6] = 7;
arr2[7] = 8;
arr2[8] = 9;
arr2[9] = 10;
Is this even safe? I worry that this will cause some strange behavior and that arr2 is just an int[5] array and you're now overwriting data that doesn't belong to it.
NO.
arr2 = arr1;
Does not do what you think it does!
There is already something in the STL for this, it's called vector.
For the sake of completeness.. :)
arr2 before the assignment held the address if the start of the array of 10 items you allocated. After the assignment, rather than copying the contents the block addressed by arr1 (which I guess is what you wanted to do), the assignment merely changes the address that arr2 holds to the address that arr1 holds (i.e. start of the 5 item array), for the rest of your code, this has two consequences:
You no longer have the address of the block of 10 items you allocated, so you have no way of releasing that block - hence you have a memory leak (should your program continue to operate)
Though you initially allocated 10 items for arr2, by the assignment, you're now addressing a block that only has 5 items, and accessing anything outside of that block of 5 (i.e. indexes 5 onwards) is likely to end in nasal daemons paying a visit with a very large cricket bat - or you may get lucky...
So what can you do:
Use std::vector<int>, one if it's design features is to take this kind of burden away
from you (unless you're interested in implementing another container), if that's the case
Use a copy operation to correctly copy the contents rather than assign the addresses, as suggested, use std::copy - or others, such as memcpy (prefer memmove - it's a little slower but is well defined for overlapping blocks etc.)
The line arr2 = arr1; leaks memory, and all the following arr2[...]= lines invoke undefined behavior as they access the array of 5 ints outside of its bounds.
To do what you wanted to do, replace arr2 = arr1; with std::copy(arr1, arr1+5, arr2); (example program: https://ideone.com/3Rohu)
To do this properly, use std::vector<int>
This leaks memory, because you are assigning pointers.
int *arr2 = new int[10];
arr2 = arr1; // this does not assign the values
The second assignment makes arr2 point to the array arr1. You loose the array you have previously allocated, and can never delete it.
To avoid this, use an std::vector.
No, it's not safe at all. When you said arr2=arr1; you didn't copy any of the data across, you just reassigned a pointer. Now the memory you allocated with int *arr2 = new int[10]; has been leaked, and arr2 points to the original 5-element array, and when you start saying things like arr2[5] = 6; you are writing beyond the end of that array and all hell may break loose.
It's not safe that's actually a memory leak. You're not doing anything with arr2 you just ended up setting arr2 to the address of r1, remember in c and c++ theres no bounds checking so you're overwriting another stackframe by doing that
Is this even safe?
No
arr2 = arr1; // assign arr1 to arr2
arr2 is also pointing to first index element of arr1. And by doing it, arr2 looses the location where it was earlier pointing to returned by new. So, there is memory leak.
Use std::vector instead to expand the array.
Just to add to the other comments which are correct. The reason why you will leak memory is that you have replaced arr2 pointer that pointed to allocated memory for arr2 with arr1 pointer. Now arr1, arr2 point to the same thing, the array of 5 elements. When you try to clean up with delete operator, you can only clean up the 5 element array since the pointer to 10 element array has been overriden.
I am currently reading some C++ source code, and I came across this:
double **out;
// ... lots of code here
// allocate memory for out
out = new double*[num];
Not entirely sure what it does, or what it means. Is it a pointer... to another pointer?
There is also the following:
double ***weight;
// allocate memory for weight
weight = new double**[numl];
I am quite confused :P, any help is appreciated.
new double*[num] is an array of double pointers i.e. each element of the array is a double*. You can allocate memory for each element using out[i] = new double; Similarly weight is an array of double**. You can allocate the memory for each weight element using new double*[num] (if it is supposed to be an array of double*)
It's a pointer to pointer to double. Or array of pointers to double. Or if every pointer itself allocates array it might be a matrix.
out = new double*[num]; // array of pointers
Now it depents if out[0] is allocated like this:
out[0] = new double; // one double
or like this:
out[0] = new double[num]; // now you've got a matrix
Actually, writing
double*[] out;
is in C/C++ equal to
double** out;
and it means an array of pointers to double. Or a pointer to pointers of double. Because an array is nothing more than just a pointer. So this is in essence a two-dimensional array.
You could as well write
double[][] out;
And likewise, adding another pointer level, will add another dimension to your array.
So
double ***weight;
is actually a pointer to a three-dimensional array.
Basically both of your code fragments allocate array of pointers. For allocation it does not matters to what. Correct declaration is needed only for type checks. Square bracjets should be read separately and means only it is array.
Consider following code as quick example:
#include <stdio.h>
int main()
{
unsigned num = 10;
double **p1, ***p2;
p1 = new double*[num];
p2 = new double**[num];
printf("%d\n", sizeof(p1));
printf("%d\n", sizeof(p2));
delete [] p1;
delete [] p2;
return 0;
}
Yes, both are just pointers. And memory allocated is sizeof(double*) * num.