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.
Related
I am wondering the ptr[i] pointer in the following code can be pointed to an integer array, why or why not. The problem is that if there exists another integer array (i.e. int brr[] = {4,5,6}), whether ptr[i] can be pointed to the integer array (i.e. brr)or it can just point to an integer(i.e. brr[i]), why or why not?
#include <stdio.h>
const int SIZE = 3;
void main()
{
// creating an array
int arr[] = { 1, 2, 3 };
// we can make an integer pointer array to
// storing the address of array elements
int i, *ptr[SIZE];
for (i = 0; i < SIZE; i++) {
// assigning the address of integer.
ptr[i] = &arr[i];
}
// printing values using pointer
for (i = 0; i < SIZE; i++) {
printf("Value of arr[%d] = %d\n", i, *ptr[i]);
}
}
An array decays to a pointer to its first element when used as an r-value. So
ptr[i] = arr;
is equivalent to
ptr[i] = &arr[0];
Since you already know that the latter is valid, so is the former.
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]).
Im kind of begginer in C++, just to programming in PHP and JAVA, I have problem to make a pointer to 2d array, then use this pointer in different function and cout values of [0] and [1].
There is part of my script.
int size_dd = 5;
int dd[size_dd][2];
for (int i = 0; i < size_dd; i ++)
{
dd[i][0] = 2 * i + 10;
dd[i][1] = 4 * i + 20;
}
I can read the dd[i][0] in main function but I cannot call them in function read(int* twodarray), as it returns int[int] and the 2nd parameter from array is lost.
Thing is that I need to make pointer to this array and call it in other function.
But the problem is when I handle *dd in to the function, it return that dd is int[int] value instead of int[int][int], how can I resolve it?
Your function should have following signature:
void fooByPtr(int(*arr)[5][6]) {
(*arr)[4][4] = 156;
}
// Call ex:
int dd[5][6];
fooByPtr(&dd);
You can also do it with reference and template:
void fooByRef(int (&arr)[5][6]) {
arr[4][4] = 156;
}
template<int N, int M>
void fooByRefTempl(int(&arr)[N][M]) {
arr[4][4] = 156;
}
Some other comments to your code (also the one from comment):
You can create arrays using constant values as sizes, so this is wrong:
int size_dd = 5;
and should be:
const int size_dd = 5;
in your fun_call you should dereference your array: (*dwu_wymiar) before indexing it.
finally, change funCall(int(*dwu_wymiar)[][2], to int(*dwu_wymiar)[5][2], as in my example above.
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)