I had a function that returns a unique_ptr to an array element, and I noticed the original variable was not getting updated.
Why does this work (a[5] == 6 after):
int a[10];
for (size_t i = 0; i < 10; i++)
{
a[i] = i;
}
int* ap = &a[5];
*ap += 1;
But
int a[10];
for (size_t i = 0; i < 10; i++)
{
a[i] = i;
}
unique_ptr<int> ap = make_unique<int>(a[5]);
*ap += 1;
Does not update the original array element? (a[5] == 5 ):
The function std::make_unique<T> constructs a new object.
Quoting:
Constructs an object of type T and wraps it in a std::unique_ptr.
Therefore, your statement
unique_ptr<int> ap = make_unique<int>(a[5]);
creates another integer (T = int) and initializes it with the value of the expression a[5].
So, when you operate on the pointer ap you are actually modifying another integer (a copy of a[5]).
Related
I have a List class for char arrays. And I want to push back N arrays from 'a' to 'a..a'.
char* x;
SList list;
for (unsigned int i = 1; i < n+1; i++) {
x = new char[i+1];
for (unsigned int j = 0; j < i; j++) {
x[j] = 'a';
}
x[i] = '\0';
list.push_back(&x);
}
But every time, x has the same address. And in result, my List object contains N pointers to the same address.
Is there a way to push back these arrays in loop with correct memory allocation?
Before asking found this question, but it doesn't provide a cool solution for my problem.
In each iteration of the loop x = new char[i+1]; returns a different address, which is stored in x. So the value of x changes in each iteration, yet, the address of x doesn't.
Did you mean
list.push_back(x);
to add the address of the newly allocated memory? Of course this would require you to change the type of list the a collection of char *.
It must be mentioned that dereferencing &x after x goes out of scope will lead to undefined behaviour, because x doesn't exist anymore. You fill list with dangling pointers.
Finally I'd like to mention that you could avoid the nasty manual memory management and simply use a std::vector<std::string>.
std::vector<std::string> list;
for (unsigned int i = 1; i < n+1; i++) {
std::string newString(i, 'a'); // string with i times 'a'
list.push_back(newString);
}
Ok. I found a pretty straightforward solution:
char** x = new char*[n];
SList sl;
for (unsigned int i = 0; i < n; i++) {
x[i] = new char[i+1];
for (unsigned int j = 0; j < i; j++) {
x[i][j] = 'a';
}
x[i][i] = '\0';
sl.push_back(&x[i]);
}
With having N addresses to store pointers to arrays. I can just add their addresses to my list object
This question already has answers here:
Difference between pointer to a reference and reference to a pointer
(6 answers)
Closed 4 years ago.
Following is a code to split an array. The
first output array will contain the input array entries in between the given two indices and the second
output array will contain the rest of the entries.
void splitArray(int *arr, int size, int ind1, int ind2,
int *&first, int &firstSize, int *&second, int &secondSize){
firstSize = ind2 - ind1 + 1;
secondSize = size - firstSize;
first = new int[firstSize];
second = new int[secondSize];
for (int i = 0; i < ind1; i++)
second[i] = arr[i];
for (int i = ind1; i <= ind2; i++)
first[i - ind1] = arr[i];
for (int i = ind2 + 1; i < size; i++)
second[i - firstSize] = arr[i];
}
The thing I can understand why it has parameters like int *&first and int *&second, arent they are same as just int first and int second but in this code they are used as pointers to dynamic arrays.
T *&foo declares a reference to a pointer to T. Don't confuse the ampersand in declarations and definitions with the address-of operator.
References to pointers are used if the called function needs to be able to modify the value of the pointer passed to it:
void bar(int *&ptr) {
ptr = 42; // change the value of the pointer (pseudo ... 42 is most likely
*ptr = 42; // change the value of the pointee not a valid pointer value)
}
// ...
int *foo = nullptr;
bar(foo);
// foo == 42;
Hint: Read types from right to left: T *& --> &* T --> reference (&) to pointer (*) to type T.
What's the meaning of the code below?
int **matrix = new int*[n]
What's the difference here between matrix and int*[n]?
It is an array of 'n' pointers, for which memory can be allocated and initialized in loop.
If n is 3, it is an array of 3 elements and each is pointer to int, can point to set of array of integer values like below.
matrix[0] -> Ox001 points to array of int [ 1 2 3 4]
matrix[1] -> Ox017 [ 5 6 7 8]
matrix[2] -> Ox024 [ 9 10 11 12]
Sample code like this
int **m = new int*[3];
for(auto i=0; i < 3; i++)
{
m[i] = new int[3];
for(auto j=0; j < 3; j++)
m[i][j] = 0;
}
for(auto i=0; i < 3; i++)
{
m[i] = new int[3];
for(auto j=0; j < 3; j++)
cout << m[i][j];
cout << "\n";
}
for instance there is cricket team and you need
Since you have Cricket* team;, this indicates you have one of two possible
situations:
1) a pointer to a single CricketPlayer (or any derived) type
2) a pointer to an array of CricketPlayer (but not derived) types.
What you want is a pointer to an array of CricketPlayer or derived types. So you
need the **.
You'll also need to allocate each team member individually and assign them to the array:
// 5 players on this team
CricketPlayer** team = new CricketPlayer*[5];
// first one is a bowler
team[0] = new Bowler();
// second one is a hitter
team[1] = new Hitter();
// etc
// then to deallocate memory
delete team[0];
delete team[1];
delete[] team;
In your query,
It can be understood as
int *matrix[]=new int*[n];
SO there are n pointers pointing to n places.
Because
int *foo;
foo=new int[5];
will also create 5 consecutive places but it is the same pointer.
In our case it is array of pointers
You need to notice some thing as follows:
int *p means that p is a pointer that points to an int variable or points to an array of int variables.
int* *p means that p is a pointer that points to an int* variable or points to an array of int* variables.
new int[5] is an array of 5 int variables.
new int*[5] is an array of 5 int* variables.
In this case, matrix is the second type so it can point to an array of int* variables so the statement:int **matrix = new int*[n] is legal
It means that you have declared a double pointer(of type int) called matrix and allocated an array of n int* pointers. Now you can use matrix[i] as an int* pointer (0 <= i < n). Later you might want to allocate memory to individual pointers as well like matrix[i] = new int[size];(size is an int or more appropriately size_t)
matrix is an object of type int **. This type is a pointer to pointer to int.
On the other hand, int * is a type, a pointer to int.
The expression:
new int*[n]
creates n adjacent objects of type int * somewhere in memory and returns a pointer to the first of them. In other words, it allocates and constructs n pointers to int; and returns a pointer to the first. Since the first (and each of them) are int *, the pointer pointing to the first is, in turn, of type int **.
It would be absolutely clear if you remember the operator associativity and precedence.
Going by that int *[n] will be interpreted by compiler : as array of " n pointer to integers".(as [ ] has greater precedence than *, so for easy understanding, compiler interprets it that way.).
Now comming to other side int ** matrix is pointer to pointer.
When you created an array of pointer,you basically have the address of the first location ,here first location stores an pointer to integer.
So,when you are storing the address of the first address of such array you will need pointer to a pointer to point the whole array.
//code for passing matrix as pointer and returning as a pointer
int ** update(int ** mat)
{
mat[0][1]=3;
return mat;
}
int main()
{ int k=4;
int **mat = new int*[k];
for(auto i=0; i < k; i++)
{
mat[i] = new int[k];
for(int j=0;j<k;j++)
{
if(i==j)
mat[i][j]=1;
else
mat[i][j]=0;
}
}
mat=update(mat);
for(auto i=0; i < k; i++)
{
for(auto j=0; j < k; j++)
cout << mat[i][j];
cout << "\n";
}
return 0;
}
Ok, so I'm quite new to C++ and I'm sure this question is already answered somewhere, and also is quite simple, but I can't seem to find the answer....
I have a custom array class, which I am using just as an exercise to try and get the hang of how things work which is defined as follows:
Header:
class Array {
private:
// Private variables
unsigned int mCapacity;
unsigned int mLength;
void **mData;
public:
// Public constructor/destructor
Array(unsigned int initialCapacity = 10);
// Public methods
void addObject(void *obj);
void removeObject(void *obj);
void *objectAtIndex(unsigned int index);
void *operator[](unsigned int index);
int indexOfObject(void *obj);
unsigned int getSize();
};
}
Implementation:
GG::Array::Array(unsigned int initialCapacity) : mCapacity(initialCapacity) {
// Allocate a buffer that is the required size
mData = new void*[initialCapacity];
// Set the length to 0
mLength = 0;
}
void GG::Array::addObject(void *obj) {
// Check if there is space for the new object on the end of the array
if (mLength == mCapacity) {
// There is not enough space so create a large array
unsigned int newCapacity = mCapacity + 10;
void **newArray = new void*[newCapacity];
mCapacity = newCapacity;
// Copy over the data from the old array
for (unsigned int i = 0; i < mLength; i++) {
newArray[i] = mData[i];
}
// Delete the old array
delete[] mData;
// Set the new array as mData
mData = newArray;
}
// Now insert the object at the end of the array
mData[mLength] = obj;
mLength++;
}
void GG::Array::removeObject(void *obj) {
// Attempt to find the object in the array
int index = this->indexOfObject(obj);
if (index >= 0) {
// Remove the object
mData[index] = nullptr;
// Move any object after it down in the array
for (unsigned int i = index + 1; i < mLength; i++) {
mData[i - 1] = mData[i];
}
// Decrement the length of the array
mLength--;
}
}
void *GG::Array::objectAtIndex(unsigned int index) {
if (index < mLength) return mData[index];
return nullptr;
}
void *GG::Array::operator[](unsigned int index) {
return this->objectAtIndex(index);
}
int GG::Array::indexOfObject(void *obj) {
// Iterate through the array and try to find the object
for (int i = 0; i < mLength; i++) {
if (mData[i] == obj) return i;
}
return -1;
}
unsigned int GG::Array::getSize() {
return mLength;
}
I'm trying to create an array of pointers to integers, a simplified version of this is as follows:
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
Now the problem is that the same pointer is used for j in every iteration. So after the loop:
array[0] == array[1] == array[2];
I'm sure that this is expected behaviour, but it isn't quite what I want to happen, I want an array of different pointers to different ints. If anyone could point me in the right direction here it would be greatly appreciated! :) (I'm clearly misunderstanding how to use pointers!)
P.s. Thanks everyone for your responses. I have accepted the one that solved the problem that I was having!
I'm guessing you mean:
array[i] = &j;
In which case you're storing a pointer to a temporary. On each loop repitition j is allocated in the stack address on the stack, so &j yeilds the same value. Even if you were getting back different addresses your code would cause problems down the line as you're storing a pointer to a temporary.
Also, why use a void* array. If you actually just want 3 unique integers then just do:
std::vector<int> array(3);
It's much more C++'esque and removes all manner of bugs.
First of all this does not allocate an array of pointers to int
void *array = new void*[2];
It allocates an array of pointers to void.
You may not dereference a pointer to void as type void is incomplete type, It has an empty set of values. So this code is invalid
array[i] = *j;
And moreover instead of *j shall be &j Though in this case pointers have invalid values because would point memory that was destroyed because j is a local variable.
The loop is also wrong. Instead of
for (int i = 0; i < 3; i++) {
there should be
for (int i = 0; i < 2; i++) {
What you want is the following
int **array = new int *[2];
for ( int i = 0; i < 2; i++ )
{
int j = i + 1;
array[i] = new int( j );
}
And you can output objects it points to
for ( int i = 0; i < 2; i++ )
{
std::cout << *array[i] << std::endl;
}
To delete the pointers you can use the following code snippet
for ( int i = 0; i < 2; i++ )
{
delete array[i];
}
delete []array;
EDIT: As you changed your original post then I also will append in turn my post.
Instead of
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
there should be
Array array;
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject( new int( j ) );
}
Take into account that either you should define copy/move constructors and assignment operators or define them as deleted.
There are lots of problems with this code.
The declaration void* array = new void*[2] creates an array of 2 pointers-to-pointer-to-void, indexed 0 and 1. You then try to write into elements 0, 1 and 2. This is undefined behaviour
You almost certainly don't want a void pointer to an array of pointer-to-pointer-to-void. If you really want an array of pointer-to-integer, then you want int** array = new int*[2];. Or probably just int *array[2]; unless you really need the array on the heap.
j is the probably in the same place each time through the loop - it will likely be allocated in the same place on the stack - so &j is the same address each time. In any case, j will go out of scope when the loop's finished, and the address(es) will be invalid.
What are you actually trying to do? There may well be a better way.
if you simply do
int *array[10];
your array variable can decay to a pointer to the first element of the list, you can reference the i-th integer pointer just by doing:
int *myPtr = *(array + i);
which is in fact just another way to write the more common form:
int *myPtr = array[i];
void* is not the same as int*. void* represent a void pointer which is a pointer to a specific memory area without any additional interpretation or assuption about the data you are referencing to
There are some problems:
1) void *array = new void*[2]; is wrong because you want an array of pointers: void *array[2];
2)for (int i = 0; i < 3; i++) { : is wrong because your array is from 0 to 1;
3)int j = i + 1; array[i] = *j; j is an automatic variable, and the content is destroyed at each iteration. This is why you got always the same address. And also, to take the address of a variable you need to use &
could someone give me a brief explanation of what is happening differently in the functions below?
void f1(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)[i].ival = i;
}
}
void f2(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)->ival = i;
(*d)++
}
}
void f3(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d->ival = i;
d++;
}
}
void f4(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d[i].ival = i;
}
}
particularly what is happening differently in f2. but clearly different things are happening in each.
f1 and f3 do the same thing (but differently). f2 fails completely, and f4 is buggy (works in this example, but when i tried to put other values into other pointers (char *) the strings end up strange.)
void f1(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)[i].ival = i;
}
}
The d seems to be a pointer to array of data_t's (or is a 1-element array of arrays of data_t). It is dereferenced to recover the array of data_t's and then i-th element of this array is modified.
void f2(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)->ival = i;
(*d)++
}
}
This is a bit tricky and indeed does something different than in the first case. There was a pointer to array of data_t's. Here we have an array of pointers to data_t's. The pointer to first element is dereferenced to retrieve a pointer to data. Then -> is used to access the data and value is modified ( x->y = (*x).y ). Finally the pointer is moved to the next element of main array.
void f3(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d->ival = i;
d++;
}
}
Here we have simpler case, the d is just an array of data_t's accessed by pointer. Inside the loop, an element is accessed by ->, and then d is incremented to point to next element of array.
void f4(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d[i].ival = i;
}
}
Similarly to f3, elements are modified by the [] operator.
Note the following facts:
int[] =(def) int *
if a is of type int * and i is of any integral type, then:
*(a + i) =(def) a[i]
Also, if a points to first element of an array, then
*a =(def) a[0]
and then, after a "a++"
*a =(def) a[1]
...and so on.
Let's take these one at a time:
// f1
(*d)[i].ival = i;
First, (*d) is dereferencing d, which appears to be a pointer to an array of data_t variables. This allows access to the actual array, such that [i] is accessing the i-th element of the array and assigning i to it.
// f2
(*d)->ival = i;
(*d)++;
(*d) is dereferencing d just like in the first one. However, there is one crucial bit of information about arrays that you should understand before moving on...
int j[2] = { 42, 50 };
int j0 = *j; // j0 is now 42
j += 1;
int j1 = *j; // j1 is now 50
Arrays are implemented as individual variables sequentially oriented in "slots" in memory, and an array is really just a pointer to the first slot. As such, *j is dereferencing j, which is currently pointing to the first element, resulting in 42. Doing j += 1 advances the pointer by one "slot", such that *j will now result in 50.
Now, back to f2. (*d)->ival is exactly like doing (**d).ival. This is very much like the simple example I gave above. The next line, (*d)++, is advancing the pointer to the next "slot". Consider this simple diagram of what's "happening" in memory:
+------+------+
|*(j+0)|*(j+1)|
j --->|------|------|
| 42 | 50 |
+------+------+
with j pointing to the first "slot", the dereference shown in the first row, the value in the second.
f3 is very much like f2, except that it expects the array to be passed as an argument, instead of a pointer to it. Hence, d only needs to be dereferenced once with the -> operator (again, exactly like (*d).ival).
f4is very much like f1, except that it expects the array to be passed as an argument, instead of a pointer to it. Hence, d[i] is directly accessing the i-ith element of the array.
void f1(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)[i].ival = i;
}
}
You get a pointer to array **d of data_t ,which element is a structure,having a field ival
Access the array *d
Iterate all array elements,element by element,changing indices i.And updating ival of each array element by to be i
Note:You dont change the pointer*d`,pointing to array beginning
void f2(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)->ival = i;
(*d)++
}
}
You get a pointer to array **d of data_t ,which element is a structure,having a field ival
Access the array *d,which is also a pointer to the array (first element)
Updating ival of the (above) element by to be i,using pointer notation (*d)->ival = i;
Promote the pointer to the next array element (*d)++ and return to 2.From now on *d is
pointing to the "sifted"array beginning.
void f3(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d->ival = i;
d++;
}
}
1.You get an array *d of data_t ,which element is sa structure,having a field ival.
2.It also can be considered you get a pointer to the first element of array.
Access access and update ival to be i,by pointer: d->ival = i;
3.Promote the pointer to the next array element d++
void f4(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d[i].ival = i;
d++;
}
}
As in f3.But you promote indices and update ival using reference notation (by value)