I am trying to reference an array by using pointers
double a[5];
double*& b = a; //doesn't compile
double*& b = &a[0]; //doesn't compile either
double*& b = &static_cast<double*>(a); //nope
Is there any way to make it so that b is binded to the address of the first element of the array?
thanks!
To reference an array by using pointers, you don't need anything
special:
double* b = a;
If you want a pointer to the entire array, rather than to just
the first element, it is:
double (*b)[5] = &a;
, but this very unusual, and will enormously confuse any reader.
If you want a reference to the entire array (no pointer):
double (&b)[5] = a;
This is often used as a function parameter, but I've never seen
it used elsewhere.
If you want a reference to a pointer designating the first
element, it has to be const, because the result of a conversion
(including the array to pointer conversion) is an rvalue, and
cannot be bound to a non-const reference:
double *const (&b) = a;
And if you really need a non-const reference to a pointer,
you'll have to introduce a pointer variable:
double* pa = a;
double* (&b) = pa;
As others have remarked, you don't need a reference-to-a-pointer, just use a pointer-to-double.
double *b = a;
The reason why you can't assign a to a reference-to-a-pointer is because the silent conversion from array-of-double to pointer-to-double results in an rvalue.
If you have to use a reference to pointer, you should make it a reference to const pointer, const references can bind to rvalues:
double a[5];
double * const &b = a;
You can get a pointer to the first element:
double * b = a;
or a const reference to an unnamed pointer to it:
double * const & b = a;
or a reference to the array:
double (&b)[5] = a;
but there's no way get a non-const reference to a pointer without a pointer variable to refer to.
In this program a pointer an array is used:
//#include <conio.h>
#include <iostream>
using namespace std;
int main()
{
int a[5] = {1,2,3,4,5};
int b[5] = {6,7,8,9,10};
int (*pa[4])[5] = {&a,&b,&a,&b};
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 5; j++)
cout<< (*pa[i])[j] << "
cout<< "\n";
}
//_getch();
cin.get();
}
In some compilers comparison of &a and a is allowed. For example this code can be compiled in (old) Borland compilers:
//#include <conio.h>
#include <iostream>
using namespace std;
int main()
{
int a[20];
cout<< (a == &a);
//_getch();
cin.get();
}
and the output is 1. But in previous program instead of
int (*pa[4])[5] = {&a,&b,&a,&b};
one cannot write
int (*pa[4])[5] = {a,b,a,b};
Related
I created a function to change the value of *a, but it remains unchanged after the function fun has been executed.
Here's my code.
#include<iostream>
using namespace std;
void fun(int *b){
int *c = new int;
*c = 4;
b = c;
}
int main(){
int *a = new int;
*a = 2;
fun(a);
cout << *a << endl; // the output is 2 but I want it be 4
return 0;
}
I want *a be 4 in function fun
There's two ways, first the C++ way is to have a mutable (non-const) reference:
void fun(int& b) {
b = 4;
}
// Calling
int x = 0;
fun(x);
Then the classic C way is to use a regular pointer:
void fun(int* b) {
*b = 4;
}
// Calling
int x = 0;
fun(&x);
The reference approach is better because there's less syntax chaff both in calling the function, and in the function's implementation. There's also no risk you might get nullptr, a reference will be defined.
Note: Your use of new here has unintended consequences, like leaking memory. When you allocate with new you are responsible for releasing that memory.
b = c;
b is pointer, this operation makes b points to the address c represents. you do not change the value located on the address of 'a'
*b = *c;
This is the right
In your function instead of b=c you should write
*b = *c to change the value stored at the address pointed by b.
That is the reason your function does not work as desired.
In case of any query please feel free to clarify.
I am trying to run the following code, but I am getting the following error.
error: cannot declare pointer to 'int&'
#include <iostream>
using namespace std;
int main()
{
int x = 5;
int *ptr = &x;
int &(*y) = ptr;
*y = 5;
cout << *ptr << endl;
return 0;
}
You declare references to pointers the same way you declare references to basic types.
Consider:
int main()
{
int i = 0; // int
int& ir = i; // int reference (reference to int)
int* ip = &i; // int pointer (pointer to int)
int*& ipr = ip; // int pointer reference (reference to pointer to int)
*ip = 5;
cout << *ipr << endl;
return 0;
}
If you just want a new pointer to the same region of memory, use:
int *y = ptr;
This not so much an "alias" in that if you change *ptr or *y, both will change, but if you change the pointers themselves, the other will not be updated.
If you actually do want a reference to a pointer, use:
int *&y = ptr;
int *ptr = &x;
pointer value has an address and a type of x.
when you typed code above, the value of ptr is an address of x, and ptr know the type of x.
int * (&y) = ptr;
the code above is declaring variable 'y' (type:int*, define:ptr's reference)
reference variables should be declared and defined simultaneously.
anyway, as a result, ptr and y are pointing same memory address.
you can easily think y is a nickname of ptr.
so you can access the variable 'x' by using y, instead of ptr.
v - a variable name.
&v - a variable that will be a reference of something.
*&v - a variable that will be a reference of a pointer to something
int *&v - a variable that will be a reference of a pointer to int
Or for a more interesting example,
(*&v)[5] - a variable that will be a reference of a pointer to an array of 5 something
int (*&v)[5] - a variable that will be a reference of a pointer to an array of 5 int
For some reason I want to assign value to the double pointer in struct member. I have structure that have 3 member's first is int, second is pointer to that int, and third is double pointer, which point to second member (to pointer). That third member don't know how to define as well. Here is source:
#include <iostream.h>
typedef struct {
int a;
int *b;
int **c;
} st;
st st1, *st2 = &st1;
void main(){
// first define a member
st1.a = 200;
// second assign b pointer member to a
st2->b = &st1.a;
// third assign c pointer member to b (but that don't work)
*(st2)->c = st2->b;
}
OS: win 7, 64, c++ (c++ Builder 2010)
typedef struct {
int a;
int *b;
int **c;
} st;
st mySt;
void main() {
mySt.a = 200;
mySt.b = &mySt.a;
mySt.c = &mySt.b;
}
With the last assignment, you get the address of field b, which is a pointer, so it is the address of a pointer, then field c is correctly initialized as a pointer to a pointer.
Try this:
st2->c = &st2->b;
Assigning a pointer-to-pointer is exactly the same as assigning a pointer-to-int. You simply give it the address of a pointer, rather than the address of an int.
I found these symbols in a function declaration several times, but I don't know what they mean.
Example:
void raccogli_dati(double **& V, double **p, int N) {
int ultimo = 3;
V = new double * [N/2];
for(int i=0; i < N/2; i++) {
V[i] = new double[N/2], std :: clog << "digita " << N/2 - i
<< " valori per la parte superiore della matrice V: ";
for(int j=i; j < N/2; j++)
std :: cin >> V[i][j], p[ultimo++][0] = (V[i][j] /= sqrt(p[i][0]*p[j][0]));
}
for(int i=1; i < N/2; i++)
for(int j=0; j < i; j++)
V[i][j] = V[j][i];
}
That is taking the parameter by reference. So in the first case you are taking a pointer parameter by reference so whatever modification you do to the value of the pointer is reflected outside the function. Second is the simlilar to first one with the only difference being that it is a double pointer. See this example:
void pass_by_value(int* p)
{
//Allocate memory for int and store the address in p
p = new int;
}
void pass_by_reference(int*& p)
{
p = new int;
}
int main()
{
int* p1 = NULL;
int* p2 = NULL;
pass_by_value(p1); //p1 will still be NULL after this call
pass_by_reference(p2); //p2 's value is changed to point to the newly allocate memory
return 0;
}
First is a reference to a pointer, second is a reference to a pointer to a pointer. See also FAQ on how pointers and references differ.
void foo(int*& x, int**& y) {
// modifying x or y here will modify a or b in main
}
int main() {
int val = 42;
int *a = &val;
int **b = &a;
foo(a, b);
return 0;
}
That's passing a pointer by reference rather than by value. This for example allows altering the pointer (not the pointed-to object) in the function is such way that the calling code sees the change.
Compare:
void nochange( int* pointer ) //passed by value
{
pointer++; // change will be discarded once function returns
}
void change( int*& pointer ) //passed by reference
{
pointer++; // change will persist when function returns
}
An int* is a pointer to an int, so int*& must be a reference to a pointer to an int. Similarly, int** is a pointer to a pointer to an int, so int**& must be a reference to a pointer to a pointer to an int.
*& signifies the receiving the pointer by reference. It means it is an alias for the passing parameter. So, it affects the passing parameter.
#include <iostream>
using namespace std;
void foo(int *ptr)
{
ptr = new int(50); // Modifying the pointer to point to a different location
cout << "In foo:\t" << *ptr << "\n";
delete ptr ;
}
void bar(int *& ptr)
{
ptr = new int(80); // Modifying the pointer to point to a different location
cout << "In bar:\t" << *ptr << "\n";
// Deleting the pointer will result the actual passed parameter dangling
}
int main()
{
int temp = 100 ;
int *p = &temp ;
cout << "Before foo:\t" << *p << "\n";
foo(p) ;
cout << "After foo:\t" << *p << "\n";
cout << "Before bar:\t" << *p << "\n";
bar(p) ;
cout << "After bar:\t" << *p << "\n";
delete p;
return 0;
}
Output:
Before foo: 100
In foo: 50
After foo: 100
Before bar: 100
In bar: 80
After bar: 80
Typically, you can read the declaration of the variable from right to left. Therefore in the case of int *ptr; , it means that you have a Pointer * to an Integer variable int. Also when it's declared int **ptr2;, it is a Pointer variable * to a Pointer variable * pointing to an Integer variable int , which is the same as "(int *)* ptr2;"
Now, following the syntax by declaring int*& rPtr;, we say it's a Reference & to a Pointer * that points to a variable of type int. Finally, you can apply again this approach also for int**& rPtr2; concluding that it signifies a Reference & to a Pointer * to a Pointer * to an Integer int.
To understand those phrases let's look at the couple of things:
typedef double Foo;
void fooFunc(Foo &_bar){ ... }
So that's passing a double by reference.
typedef double* Foo;
void fooFunc(Foo &_bar){ ... }
now it's passing a pointer to a double by reference.
typedef double** Foo;
void fooFunc(Foo &_bar){ ... }
Finally, it's passing a pointer to a pointer to a double by reference. If you think in terms of typedefs like this you'll understand the proper ordering of the & and * plus what it means.
This *& in theory as well as in practical its possible and called as reference to pointer variable. and it's act like same.
This *& combination is used in as function parameter for 'pass by' type defining. unlike ** can also be used for declaring a double pointer variable.
The passing of parameter is divided into pass by value, pass by reference, pass by pointer.
there are various answer about "pass by" types available. however the basic we require to understand for this topic is.
pass by reference --> generally operates on already created variable refereed while passing to function e.g fun(int &a);
pass by pointer --> Operates on already initialized 'pointer variable/variable address' passing to function e.g fun(int* a);
auto addControl = [](SomeLabel** label, SomeControl** control) {
*label = new SomeLabel;
*control = new SomeControl;
// few more operation further.
};
addControl(&m_label1,&m_control1);
addControl(&m_label2,&m_control2);
addControl(&m_label3,&m_control3);
in the above example(this is the real life problem i came across) i am trying to init few pointer variable from the lambda function and for that we need to pass it by double pointer, so that comes with d-referencing of pointer for its all usage inside of that lambda + while passing pointer in function which takes double pointer, you need to pass reference to the pointer variable.
so with this same thing reference to the pointer variable, *& this combination helps. in below given way for the same example i have mentioned above.
auto addControl = [](SomeLabel*& label, SomeControl*& control) {
label = new SomeLabel;
control = new SomeControl;
// few more operation further.
};
addControl(m_label1,m_control1);
addControl(m_label2,m_control2);
addControl(m_label3,m_control3);
so here you can see that you neither require d-referencing nor we require to pass reference to pointer variable while passing in function, as current pass by type is already reference to pointer.
Hope this helps :-)
Is it compulsory to initialize t in the following code, before assigning value to t? Is the code correct?
void swap(int *x, int *y)
{
int *t;
*t = *x;
*x = *y;
*y = *t;
}
You don't need pointer to begin with:
void swap(int *x,int *y)
{
int t; //not a pointer!
t=*x;
*x=*y;
*y=t;
}
int a = 10, b = 20;
swap( &a, &b); //<-----------note : Needed &
--
Or maybe, you want the following swap function:
void swap(int & x,int & y) //parameters are references now!
{
int t; //not a pointer!
t=x;
x=y;
y=t;
}
int a = 10, b = 20;
swap(a,b); //<----------- Note: Not needed & anymore!
is the following section of code correct?
Nopes! Your code invokes Undefined behaviour because you are trying to dereference a wild pointer.
int *t;
*t=*x; // bad
Try this rather
int t; // a pointer is not needed here
t=*x;
or this
int *t = x; // initialize the pointer
That code contains undefined behavior:
int *t;
*t=*x; // where will the value be copied?
Besides that it makes no sense - you need a temporary variable to store the value, not the pointer.
int t; // not a pointer
t=*x;
*x=*y;
*y=t;
It's correct for a pointer.
Only references need to be initialized upon declaration (or in a constructor for instance members).
EDIT: but you got errors in your code, you shouldn't be dereferencing your parameters (ie int *ptr = otherPtr; is fine, not int *ptr = *otherPtr;)
If you just want to make your pointer point to already-initialized data, then you don't need to initialize it. The way you do it, though, yes, you want to use one of the malloc functions to allocate enough heap space for an integer.
The proper, efficient way, to do swapping in C/C++ is
void swap(int *x, int *y) {
int *t = x;
x = y;
y = t;
}
You can find the right way of doing this here
#include <stdio.h>
void swap(int *i, int *j)
{
int t;
t = *i;
*i = *j;
*j = t;
}
Basically the reason has been explained to you by sharptooth but there you will find some more details and explanations about what happens in background when you do such a swap. Hope it helps to clear your ideas.
int *t;
*t=*x;
t is not pointing to any valid location to be able to dereference.
is it compulsory to initialize , before assigning value to pointer t.
Yes, initializing / assigning to point to a valid memory location. Else where would it point to. It might some point to garbage and lead to undefined behavior on dereferencing.