I saw someone using this in one answer:
void methodA(const int*& var);
I couldn't understand what the argument means.
AFAIK:
const int var => const int value which can't be changed
const int* var => pointer to const int, ie *var can't be changed but var can be changed
const int& var => reference to const int, ie value of var can't be changed
What does const int*& var mean? Is const int& *var also possible?
Can you please give some example as well, like what can and can't be done with it?
UPDATE:
I am not sure if I am thinking the right way, but I began to think of a reference as an alias of the variable that was passed as argument, so:
const int * p;
methodA(p) => here we are passing p as const int * but we don't know if this is pass by value or what, until we see the definition of methodA, so if methodA is like this:
methodA(const int * & p2) ==> here p2 is another name to p, ie p and p2 are the same from now on
methodA(const int* p2) ==> here p2 is passed as value, ie p2 is just local to this method
Please correct me if I am thinking the wrong way. If yes, I might need to study some more about this. Can you please point to some nice references?
UPDATE 2:
If some beginner like me wants to know more about this thing, you can use the c++decl / cdecl program from here, which I just discovered to be very useful.
$ c++decl
Type `help' or `?' for help
c++decl> explain const int&* p
declare p as pointer to reference to const int
c++decl> explain const int*& p
declare p as reference to pointer to const int
But, as every one here pointed out, the first example isn't legal in C++.
It is a reference to a pointer to an int that is const.
There is another post somewhat related, actually, here. My answer gives a sorta of general algorithm to figuring these things out.
This: const int& *var has no meaning, because you cannot have a pointer to reference.
If the const's and pointers are getting in the way, remember you can typedef these things:
typedef int* IntPointer;
typedef const IntPointer ConstIntPointer;
void foo(ConstIntPointer&); // pass by reference
void bar(const ConstIntPointer&); // pass by const reference
void baz(ConstIntPointer); // pass by value
Might make it easier to read.
If you need more help on C++, read this. More specifically, references.
References as variables do not take space:
int i; // takes sizeof(int)
int*pi = &i; // takes sizeof(int*)
int& ri = i; // takes no space.
// any operations done to ri
// are simply done to i
References as parameters use pointers to achieve the end effect:
void foo(int& i)
{
i = 12;
}
void foo_transformed(int *i)
{
*i = 12;
}
int main()
{
int i;
foo(i); // same as:
foo_transformed(&i); // to the compiler (only sort of)
}
So it's actually passing the address of i on the stack, so takes sizeof(int*) space on the stack. But don't start thinking about references as pointers. They are not the same.
Some folks find it easier reading this from right to left. So
const int*&
is a reference to a pointer to an integer that is const.
As you know, references cannot be changed, only what they refer to can be changed. So the reference will refer to just one pointer to an integer that is const. Since the pointer is not const - the integer is const - you can change the pointer to point to a different integer.
Compare this to
int* const &
This is a reference to a constant pointer to an integer. Again the reference is immutable, and in this case it is a reference to a constant pointer. What you can change in this case is the integer value since there was no const either side of the int keyword.
Just to add confusion, const int and int const are the same. However int const * and int * const are very different. The first is a pointer to a constant integer, so the pointer is mutable. The second is a constant pointer to an integer, so the integer is mutable.
Hope this helps!
In your example, var is a refernce to a pointer to const char.
Since it's a reference, a change to the parameter inside methodA() will be reflected in the argument that is passed to methodA():
void methodA( const char*& var)
{
static const char newdata[] = {'a', 'b', 'c', '\0'};
printf( "var points to %s\n", var);
var = newdata;
}
int main()
{
const char * p = "123";
printf( "p points to: %s\n", p); // prints "p points to: 123"
methodA( p);
printf( "now p points to: %s\n", p); // prints "now p points to: abc"
}
It is a reference to a const pointer, i.e. a pointer where you cannot modify the data pointed to. As the reference is used as an argument to a method the method is able to modify the pointer to let it point to something else (still something that cannot be modified).
With regards to your update:
so if methodA is like this methodA(const int * & p2) ==> here p2 is another name to p, i.e. p and p2 are same from now on and if methodA(const int* p2) ==> here p2 is passed as value i.e p2 is just local to this method
Yes, you are correct.
Here's another example, a getter that returns the address of a private data item. The item happens to be an int for simplicity. A large array of items would be a more practical case (a zero-copy getter).
#include <iostream>
using namespace std;
class X {
public:
void getter(const int *&data) const
{
data = &val;
}
private:
int val = 5;
};
main()
{
X obj;
const int *data;
obj.getter(data);
cout << data << endl;
cout << *data << endl;
}
Related
This question already has answers here:
What is the difference between const int*, const int * const, and int const *?
(23 answers)
Closed last year.
I have a program like below and expect that:
with function void myFunc1 ( const int *x) ==> I cannot change the value of at the memory location that x points to, but can change the memory location that x points to.
with function void myFunc2 ( int const *x) ==> I cannot change the location that x points to as it is a const pointer. But I could change the value at the memory location that x points to.
However, upon compiling the code, I don't see the difference between const int *x vs int const *x:
in both function, the lines *x=8 in both function return error. I didn't expect error from myFunc2 because it is a const pointer, not a pointer to a const value.
in myFunc1, I expected to see value 5 after myFunc1 is close.
Could the experts here explain my 2 unexpected results above ? Here is my code:
#include "stdio.h"
int a = 5; // declared a global,
void myFunc1 ( const int *x) { // const parameter: pointer to a const int value.
// *x= 8; // error: assignment of read-only location ‘* x’ ==> cannot change the value at the location pointed by pointer. This is expected
printf("%d \n ", *x);
x = &a; // can change where the pointer point to.
// a is global and is not loss after closing myFunc2
printf("value in myFunc1: %d \n ", *x);
}
void myFunc2 ( int const *x) { // const parameter: const pointer, cannot change the address that x points to.
// *x= 8; // error: assignment of read-only location ‘* x’
printf("%d \n ", *x);
x = &a; // no compiling error here. This is not expected.
printf("value in myFunc2: %d \n ", *x);
}
int main() {
int *y;
int z = 6;
y = &z;
printf("value before myFunc1: %d \n", *y);
myFunc1(y);
printf("value after myFunc1: %d \n", *y); // expect to print 5. Result: print 6.
printf("value before myFunc2: %d \n", *y);
myFunc2(y);
printf("value after myFunc2: %d \n", *y); // expect to print 8 if the line *x=8 could be compiled . Result: print 6.
return 1;
}
I don't see the different between having 2 parameters (const int *x) vs (int const *x):
That's because int const* and const int* are the same thing.
If you want to make the pointer const, you have to put a const on its right, like this: int * const, a constant pointer to (non-constant) integer.
Unrelated (is it?) note on East const
I am one of those in favour of the so called East const, which means I prefer writing the const always on the right of what it applies to. For instance,
for a "pointer to constant int", I write int const *,
for a "constant pointer to constant int", I write int const * const.
As you see, the sentences in quotes map to the types if you read them right-to-left:
// 1 2 3 4 4 3 2 1
int const * const // constant pointer to constant int
Furthermore, always thinking of const as something that can be put on the right of what it applies to has also other advantages, sometimes in terms of peculiarities of the language that you can discover.
For instance, the following is how I discovered something more about references.
Take the declaration of a function parameter taken by reference to constant: int const& p. If you write it like this and think of it the East const way, it is clear that it declaring a p which is a reference to a constant int, not a constant reference to int.
After all, thinking East const, what would a constant reference to int look like? It'd be int & const, with the const on the right of what we'd like it to apply to, the reference &. However, this syntax is incorrect.
Why is that? Why can't I make a reference constant? Because it always is, as references cannot rebind. The standard simply doesn't let you write something totally redundant as a const applied to a reference.
I wrote the following code:
#include <iostream>
using namespace std;
const int * myFunction()
{
int * p = new int(5);
return p;
}
int main()
{
int * q = myFunction();
cout << "*q=" << *q;
cout << endl;
return 0;
}
I purposely wrote the above code to receive an error. The mistake I made is that I stated the return type of function myFunction() as const int * but when I called myFunction() in main(), the pointer variable q was not declared const. The return type of myFunction() must match exactly to the type of variable which is going to receive its return value (am I correct here? This is what I have understood).
So, I fixed the error by correcting line 11 as const int * q = myFunction();. Now the type of the (pointer)variable q, which is const int *, matched exactly to the return type of myFunction() and the code compiled without error, producing output as *q=5 (is my understanding up to this point correct?).
Then, I wrote the following code:
#include <iostream>
using namespace std;
const int * const myFunction()
{
int * p = new int(5);
cout << "p: " << p;
return p;
}
int main()
{
int a;
const int * q = myFunction();
cout << "\nq=" << q;
cout << "\n*q=" << *q;
delete q;
q = &a;
cout << "\nq: " << q;
cout << endl;
return 0;
}
I was expecting an error here, too. Because now the return type of myFunction() is const int * const but the (pointer)variable q had type const int *. q was not declared as a constant pointer. But the program compiled and I got output as follows:
p: 0x36cb8
q=0x36cb8
*q=5
q: 0x61ff08
I am confused why the second code compiles and runs. What I thought is whoever is going to receive the return value from myFunction() should always take care of it (i.e. it cannot be allowed to take a different memory address), but the pointer variable q took a different memory location.
The return type of myFunction must match exactly to the type of variable which is going the receive it's return value. (Am I correct here? This is what I have understood.)
No, the return type must not match exactly to the type of the variable. But it must be possible to implicitly convert the return type to the type of the variable.
For example something like this will compile:
int someInt = getMeAFloat();
If getMeAFloat returns a float, this will compile because a float can be implicitly converted to an int. (Note that this gives you a warning and is bad because you lose the extra information of the float, but I am just trying to bring my point across)
Your first example does not compile because normally a const int* can not be converted to a int*.
As pointed out by user4581301 the second const in your second example does not matter, because only the value of the pointer, which is returned, gets assigned to the pointer in the main function. The second const makes the pointer itself constant, which has no effect on the value.
That means that const int * const myFunction() is equal to const int * myFunction()
In the 2nd code, q is a const int * - a non-const "pointer to a const int". Since q itself is not const, it can be re-assigned to point at a new address.
The compiler allows q = &a; because an int* (ie, what &a returns since a is an int) can be assigned to a const int*. In other words, a "pointer to non-const data" can be assigned to a "pointer to const data", effectively making read-only access to otherwise-writable data.
The reverse is not true - a "pointer to const data" cannot be assigned to a "pointer to non-const data", as that would allow writable access to read-only data - which is why the 1st code fails to compile.
I've heared that C++ reference variables are implemented using pointers. I've been looking at some C code a while before i started with C++, I would because of that like to have something which i can relate to in the C language. Does anyone actually have an example on how it is implemented using pointers?
I've been doing some research on the question, this is what i've found. However, i'm not sure if it is legit or not as i've not been able to run this properly in a C++ file before. Any answers will be appreciated, thanks! :)
int& = *(int const *)
A reference has the same meaning as a constant pointer.
The code for references and pointers is the same, at least with MSVC2013.
For example:
int u=1,v=3, w;
int& x = u; // initialize reference
w = x; // x is synonym for u;
x++;
int *y = &u; // initalize pointer
w = *y; // y points to u
(*y)++;
The initialisation generates in both case:
lea eax, DWORD PTR _u$[ebp]
mov DWORD PTR _x$[ebp], eax ; of course in the case of the pointe _y$ instead of _x$.
The assignment, in both case generates:
mov eax, DWORD PTR _x$[ebp]
mov ecx, DWORD PTR [eax]
mov DWORD PTR _w$[ebp], ecx
And even the increment generates the same code.
The code generated is the same for whether it is a pointer, a const pointer, or a poitner to const (in the latter case, the ++ does not work). It's the compiler buisness to make sure that const is const.
Now there is a subtle difference in syntax:
int& x = u; // initialize reference
int *y = &u; // initalize pointer
int const *z = &u; // initialize pointer to "const int". Pointer itself is not const !
int * const a = &u; // initialize "const pointer" to "int", which is basically a reference.
With these definitions:
//(*z)++; // invalid because the it points to a const int.
z = &w; // valid because pointer intself is not const
and:
(*a)++; // valid because the it points to an int.
// a = &w; // invalid because it's a const pointer
So you could say int& is pretty much equivalent to int * const (I don't use '=' here, because it is reserved to the operator= and looks like a syntax error !)
Of course, with the reference you always use its name as if it was a real variable (ex: x++) while with the const pointer you always have to dereference (aka: (*x)++). So same meaning, but different syntax.
This is the best proof I can think of:
#include <iostream>
using namespace std;
double value;
struct pointer {
double *value; };
struct reference {
double& value; };
int main() {
pointer ptr { &value };
reference ref { value };
*ptr.value = 3.14;
cout << sizeof(value) << endl;
cout << sizeof(pointer) << endl;
cout << sizeof(reference) << endl;
cout << ref.value;
}
Output:
8
4
4
3.14
Can you see the sizes? sizeof(pointer) == sizeof(reference) but not sizeof(value).
Regarding that added/edited example in the question int& = *(int const *):
ref.value = *ptr.value; ref.value = *(double*)ref.value; //no const
ref.value = *(double const *)ptr.value; // yes, we can add const before *
int i = 1; const j = 2;
const int& cri = *(const int const *)&i; // same as *&i and simple i, notice two consts
const int& crj = j;
int& rj = j; // error: const cannot be removed that way
In other words: References are constant pointers (cannot be changed) with a different set of operators. The main advantage is that compilers can optimize them better (discard the reference/pointer completely), but that does not proof that they are any different because compilers can optimize/discard pointers as well (and gcc -O3 can do that well, I have seen and dissassembled good loop with pointers, where gcc could overcome so called aliasing problem).
A compiler can implement references any way that works, including that some references are completely optimized away.
You can think of the reference
T& r = o;
as
T* const pr = &o;
#define r (*pr)
which serves as a nice explanation of most properties of lvalue references, except that this conceptual picture does not include lifetime extension of temporaries and initialization with a temporary.
It “explains” that
a reference must be initialized in the declaration, except when it’s a formal argument,
a reference can’t be reassigned,
a reference can’t be a “null-reference” in valid code.
But keep in mind that it’s only a conceptual picture: while it’s very likely to be the underlying reality for much of the generated code, it is by no means a requirement that a compiler implements a reference this way.
You might find the section about references in the C++ FAQ instructive.
In C, when you use a variable as a parameter to a function, it is sent by value. If the function is supposed to change the variable, then the parameter must be sent as a pointer.
int x = 5;
void addtwo(int* param)
{
*param += 2;
}
addtwo(&x); // This will send a pointer to x to the function addtwo
In C++, you can send a reference:
void addtwo(int& param)
{
param += 2;
}
addtwo(x); // This will send a reference to x to the function addtwo
This doesn't look like much of a difference in this simple example, but in the second one, it looks like param is not being dereferenced. But it actually is, since it was sent as a reference. Even though param does not look like a pointer (and it isn't - it's a reference) the function addtwo is sent the address of x, very much as if it were a pointer. The difference is subtle, but concrete.
I am trying to understand char pointer in C more but one thing gets me.
Supposed I would like to pass a char pointer into a function and change the value that pointer represents. A example as followed:
int Foo (char *(&Msg1), char* Msg2, char* Msg3){
char *MsgT = (char*)malloc(sizeof(char)*60);
strcpy(MsgT,"Foo - TEST");
Msg1 = MsgT; // Copy address to pointer
strcpy(Msg2,MsgT); // Copy string to char array
strcpy(Msg3,MsgT); // Copy string to char pointer
return 0;
}
int main() {
char* Msg1; // Initial char pointer
char Msg2[10]; // Initial char array
char* Msg3 = (char*)malloc(sizeof(char) * 10); // Preallocate pointer memory
Foo(Msg1, Msg2, Msg3);
printf("Msg1: %s\n",Msg1); // Method 1
printf("Msg2: %s\n",Msg2); // Method 2
printf("Msg3: %s\n",Msg3); // Method 3
free(Msg1);
free(Msg3);
return 0;
}
In the above example, I listed all working methods I know for passing char pointer to function. The one I don't understand is Method 1.
What is the meaning of char *(&Msg1) for the first argument that is passed to the function Foo?
Also, it seems like method 2 and method3 are widely introduced by books and tutorials, and some of them even referring those methods as the most correct ways to pass arrays/pointers. I wonder that Method 1 looks very nice to me, especially when I write my API, users can easily pass a null pointer into function without preallocate memory. The only downside may be potential memory leak if users forget to free the memory block (same as method 3). Is there any reason we should prefer using Method 2 or 3 instead Method 3?
int f(char* p) is the usual way in C to pass the pointer p to the function f when p already points to the memory location that you need (usually because there is a character array already allocated there as in your Method 2 or Method 3).
int f(char** p) is the usual way in C to pass the pointer p to the function f when you want f to be able to modify the pointer p for the caller of this function. Your Method 1 is an example of this; you want f to allocate new memory and use p to tell the caller where that memory is.
int f(char*& p) is C++, not C. Since this compiles for you, we know you are using a C++ compiler.
Consider what happens when you take an argument of type int& (reference to int) :
void f(int &x) {
x++;
}
void g(int x) {
x++;
}
int main() {
int i = 5;
f(i);
assert(i == 6);
g(i);
assert(i == 6);
}
The same behaviour can be achieved by taking a pointer-to-int (int *x), and modifying it through (*x)++. The only difference in doing this is that the caller has to call f(&i), and that the caller can pass an invalid pointer to f. Thus, references are generally safer and should be preferred whenever possible.
Taking an argument of type char* (pointer-to-char) means that both the caller and the function see the same block of memory "through" that pointer. If the function modifies the memory pointed to by the char*, it will persist to the caller:
void f(char* p) {
(*p) = 'p';
p = NULL; //no efect outside the function
}
int main() {
char *s = new char[4];
strcpy(s, "die");
char *address = s; //the address which s points to
f(s);
assert(strcmp(s, "pie") == 0);
assert(s == address); //the 'value' of the variable s, meaning the actual addres that is pointed to by it, has not changed
}
Taking an argument of type char*& ( reference-to-(pointer-to-char) ) is much the same as taking int&:
If the function modifies the memory pointed to by the pointer, the caller will see it as usual. However, if the function modifies the value of the pointer (its address), the caller will also see it.
void f(char* &p) {
(*p) = 'p';
p = NULL;
}
int main() {
char *s = new char[4];
strcpy(s, "die");
char *address = s; //the address which s points to
f(s);
assert(strcmp(address, "pie") == 0); //the block that s initially pointed to was modified
assert(s == NULL); //the 'value' of the variable s, meaning the actual addres that is pointed to by it, was changed to NULL by the function
}
Again, you could take a char** (pointer-to-pointer-to-char), and modify f to use **p = 'p'; *p = NULL, and the caller would have to call f(&s), with the same implications.
Note that you cannot pass arrays by reference, i.e. if s was defined as char s[4], the call f(s) in the second example would generate a compiler error.
Also note that this only works in C++, because C has no references, only pointers.
You would usually take char** or char*& when your function needs to return a pointer to a memory block it allocated. You see char** more often, because this practice is less common in C++ than in C, where references do not exist.
As for whether to use references or pointers, it is a highly-debated topic, as you will notice if you search google for "c++ pointer vs reference arguments".
If I have a function that takes int *&, what does it means? How can I pass just an int or a pointer int to that function?
function(int *& mynumber);
Whenever I try to pass a pointer to that function it says:
error: no matching function for call to 'function(int *)'
note: candidate is 'function(int *&)'
It's a reference to a pointer to an int. This means the function in question can modify the pointer as well as the int itself.
You can just pass a pointer in, the one complication being that the pointer needs to be an l-value, not just an r-value, so for example
int myint;
function(&myint);
alone isn't sufficient and neither would 0/NULL be allowable, Where as:
int myint;
int *myintptr = &myint;
function(myintptr);
would be acceptable. When the function returns it's quite possible that myintptr would no longer point to what it was initially pointing to.
int *myintptr = NULL;
function(myintptr);
might also make sense if the function was expecting to allocate the memory when given a NULL pointer. Check the documentation provided with the function (or read the source!) to see how the pointer is expected to be used.
Simply: a reference to a pointer.
In C, without references, the traditional way to "relocate" a pointer, is to pass a pointer to a pointer:
void c_find(int** p, int val); /* *p will point to the node with value 'val' */
In C++, this can be expressed by the reference syntax, to avoid the awkward double dereference.
void cpp_find(int*& p, int val); // p will point to the node with value 'val'
It means a reference to a pointer to an int. In other words, the function can change the parameter to point to something else.
To pass a variable in, just pass an int*. As awoodland points out, what's passed in must be an l-value.
Edit:
To build on awoodland's example:
#include <iostream>
void foo(int*& var)
{
delete var;
var = new int;
}
int main(int argc, char* argv[])
{
int* var = NULL;
std::cout << var << std::endl;
foo(var); // this function can/will change the value of the pointer
std::cout << var << std::endl;
delete var;
return 0;
}
function takes a single parameter, mynumber which is a reference to a pointer to an int.
This is useful when you need to pass a pointer to a function, and that function might change the pointer. For example, if you function is implemented like this:
function(int*& mynumber)
{
if( !mynumber )
mynumber = new int;
*mynumber = 42;
}
...Then something like this might happen in the calling code:
int main()
{
int* mynumber = 0;
function(mynumber); // function will change what "mynumber" points to
cout << *mynumber;
return 0;
}
This is a reference to a pointer to int - you would have to pass in the address of an int to this function, and be aware that the function could change the pointer through the reference.
Dumb example:
void func(int*& iref)
{
iref = new int;
}
int main()
{
int i(0);
int* pi(&i);
func(pi);
// pi no longer equal to &i
return 0;
}