#include <iostream>
void f(const int * & p)
{
int i =0;
i = p[0];
std::cout << i << std::endl;
}
int main()
{
int * p =new int[1];
p[0] =102;
f(p);
return 1;
}
The gcc compiler gives error for this code:
prog.cpp: In function ‘int main()’:
prog.cpp:16: error: invalid initialization of reference of type ‘const int*&’ from expression of type ‘int*’
prog.cpp:5: error: in passing argument 1 of ‘void f(const int*&)’
But if I change the "f" function into
void f(const int * const & p)
Everything is ok. Can somebody explain why const behaves this way? thanks.
Going from int* to const int* requires creating a temporary const int* pointer and binding the reference const int*& to that temporary.
The Standard forbids doing that creating of a temporary for non-const references. You therefor need to make the reference const as you did your fix.
This is because non-const references mean "I want to change the argument that the caller passes using that reference parameter". But if the caller needs to convert their argument and ends up passing a temporary, the point of the reference is for naught, and so the Standard deems it an error to try and pass the temporary.
If the first conversion (int * to const int * &) were allowed, then you could write an evil function like this:
const int really_const[] = {1,2,3};
void evil(const int * & p)
{
p = really_const;
}
int main()
{
int not_const[3];
int * p = not_const;
evil(p);
p[0] = 0; // Whoops: modifying a const object
}
The second conversion is fine, since it prevents the function from modifying the pointer in this way.
Related
This question already has answers here:
Binding a const pointer reference to a non-const pointer
(2 answers)
Closed 11 months ago.
before writing, I'm not good at english. So maybe there are many awkward sentence.
void Func1(const int* _i) { };
void Func2(const int& _j) { };
void Func3(const int* (&_k)) { };
int main()
{
int iNum = 1;
int* pInt = new int(1);
Func1(pInt); // works;
Func2(iNum); //works
Func3(pInt); // error
}
I use Visual Studio and error message said
"Cannot convert argument 1 from 'int *' to 'const int *&'"
I know it cant convert because of '&'. _i equals pInt so it may change dereference.
But i used const. so i think it will work but const keyword doesnt work.
why const keyword doesnt work unlike other cases? ex)Func1,Func2
Func1(pInt); // works; int* could convert to const int* implicitly
Func2(iNum); //works; int could be bound to const int&
Func3(pInt); // error;
pInt is a int*, when being passed to Func3 which expects a reference to const int*, then it would be converted to const int*, which is a temporary and can't be bound to lvalue-reference to non-const like const int* & (lvalue-reference to non-const pointer to const int).
If you change the parameter type of Func3 to int* &, then no conversion is required, pInt could be bound directly. Or change to const int* const & (lvalue-reference to const pointer to const int) or const int* && (rvalue-reference) which could bind to temporary.
why I need intermediate variable to pass my return pointer by reference instead of just using the function that returns that pointer ?
This doesn't compile
int main ()
{
testfunc(getpointer());
return 0;
}
error: C2664: 'void testfunc(int *&)': cannot convert argument 1 from 'int *' to 'int *&'
and this compiles
int main ()
{
int *i = getpointer();
testfunc(i);
return 0;
}
my two functions
void testfunc(int *& i) // I have to use this interface
{
cout << i[0] <<endl;
}
int* getpointer()
{
int * arr1 = new int[1];
arr1[0]=10;
return arr1;
}
The C++ language prohibits binding a non-const reference to a temporary. In this case, the simple fix is to make testfunc take a const reference to an int*.
Program 1
#include <iostream>
#include<string>
using namespace std;
void fun(const char *a)// passing address of "GeeksForGeeks" by value //
{
cout << "const fun() " << a;
}
void fun(const char *&a){// passing address of "GeeksForGeeks" by reference //
cout << "const reference fun()" <<a;
}
int main()
{
const char * ptr = "GeeksforGeeks";
fun(ptr);
return 0;
}
error shown
In function 'int main()':
17:8: error: call of overloaded 'fun(const char*&)' is ambiguous
fun(ptr);
^
17:8: note: candidates are:
6:6: note: void fun(const char*)
void fun(const char *a)
^
11:6: note: void fun(const char*&)
void fun(const char *&a){
^
Program 2
#include <iostream>
#include<string>
using namespace std;
void fun(const char *a)// passing address of "GeeksForGeeks" by value //
{
cout << "const fun() " << a;
}
void fun(const char *&a){// passing address of "GeeksForGeeks" by reference //
cout << "const reference fun()" <<a;
}
int main()
{
const char * const ptr = "GeeksforGeeks";
fun(ptr);
return 0;
}
Output
const fun() GeeksforGeeks
In your first version, there is an ambiguity, because ptr, which is of type const char* can be cast into const char*&. In the second version, there is no ambiguity, because this time ptr is of type const char* const, which cannot be cast into const char* &.
In general C const cannot be cast into the type C&.
void f(int& x) { cout << x; }
void main() {
int a = 2;
f(a); // This is fine
int const b = 2;
f(b); // Error: 'void f(int &)' : cannot convert argument 1 from 'const int' to 'int &'
}
In the first program, you call fun() with a pointer to const char. Two candidates are available (by value and by reference), and the compiler can't know which one to chose.
In the second program, you call fun() with a const pointer to const char. The compiler then can eliminate the version passed by reference, because this overload doesn't give guarantee that the pointer passed by reference will remain unchanged.
Additional remark: if the signature of the second function would give pointer constness guarantee (aka: void fun(const char * const &a) ) the compiler wouldn't be able to choose neither in the first nor in the second case.
Why can't I take a reference to s2 in foo? I'm compiling with gcc 5.1.0:
#include <cstring>
void foo(const char*& p)
{
while (*p && *p <= '5')
++p;
}
int main()
{
const char *s1 = "1234567890";
char *s2 = new char[strlen(s1) + 1];
strcpy(s2, s1);
foo(s1); // OK
foo(s2); // error
return 0;
}
I compiled with:
$ g++ test_reference.cpp
The compiler gave me:
test_reference.cpp: In function ‘int main()’:
test_reference.cpp:16:11: error: invalid initialization of non-const reference of type ‘const char*&’ from an rvalue of type ‘const char*’
foo(s2); // error
^
test_reference.cpp:3:6: note: initializing argument 1 of ‘void foo(const char*&)’
void foo(const char*& p)
^
For simplicity, you are trying to do:
char* s = ...;
const char*& r = s;
The const here may be misleading. You would think this is equivalent to:
int i = 4;
const int& ri = i;
Which works. But these are not equivalent. ri here is a reference to a const type, but r is a reference to a pointer to const char, that is not a const type.
The ultimate issue is that char* and char const* are not reference-related (meaning that the types are either the same or in the same hierarchy). However, if your reference was a reference to a const type, it would work fine. That is:
const char* const& cr = s;
Basically, you can take an lvalue reference to a non-const type T only from a reference-related type or from a class that is convertible to a reference related type. But you can take an lvalue reference to a const type from a much wider source of expressions:
double d = 4.0;
int& ri = d; // error: int, double aren't reference-related
const int& rci = d; // OK
You can cast it to const reference.
foo((const char *&) s2);
So I have this code and I have a problem with passing the argument into the function. When I compile I get the following error: invalid initialization of reference of type 'const Point&' from expression of type 'const Point*'
struct Point
{
int x,y;
};
void printPoint(const Point& p)
{
cout<<"The X-coordinate is = "<<p.x<<"\nThe Y-coordinate = "<<p.y<<endl;
}
int main()
{
const Point p1 = {3,4};
printPoint(&p1);
}
&pi is of type Point* (it's the address of that object), use: printPoint(p1);
References are implicit. You do not need the &. In fact, that makes it a pointer (a const Point*, which is not implicitly convertible to a const Point&). Just do printPoint(p1);.
int main()
{
const Point p1 = {3,4};
printPoint(p1);
}
&p1 gives the address of p1.
this takes reference
void printPoint(const Point& p)
but you pass a pointer
printPoint(&p1);
so, use this one:
printPoint(p1);