0

I've read that a non-const member function of a class can only be called on non-const objects. My question is, why can a non-member function which takes a non-const pointer, be called with a const pointer? I tried this code:

 int k = 10;
 int x = 5;
void func(int *n) {
    n = &k; 
    cout << *n<< ", x: " << x << endl;
}
int main()
{
     int * const ptr=&x; 
     cout << *ptr << endl; //prints 5
     cout <<"x:"<< x << endl; //prints x:5
     //ptr = &k; //compiler error
     cout << "ptr value (address): " << ptr << endl; //prints 001DC038
    func(ptr); //prints 10, x: 5
    cout << "x:" << x << endl; //x: 5
    cout << *ptr << endl; //5
    cout << "ptr value (address): " << ptr; //prints 001DC038
}

I'm not sure I understood it right, but the line func(ptr) calls func() with ptr's value which is &x, and n=&k is supposed to change x's address to k's address? but it prints different values for *n and x, so what exactly was sent to func()? Is the syntax wrong?

Itamar Ivri
  • 117
  • 6
  • 1
    You should read this excellent question https://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-and-int-const – Alessandro Teruzzi Feb 16 '21 at 17:46
  • You sent the pointer to `func` _by value_, meaning `n` was a copy of `ptr`. Also `ptr` is a `const` pointer to a non-`const` `int`, not a pointer to a `const int`. – Nathan Pierson Feb 16 '21 at 17:46
  • @S.M. I haven't. What I'm trying to do is to see if it's possible to call a function with a const pointer instead of non-const pointer – Itamar Ivri Feb 16 '21 at 17:54

2 Answers2

2
int * const ptr=&x; 

declares a immutable pointer (you can't change the address stored in ptr) that points to a mutable int (you can change the value ptr points to).

void func(int *n)

takes a pointer to a mutable int by value, no problems here. The mutability of ptr is of no concern, because you take a copy anyway. Speaking of taking copies:

 n = &k; 

will only modify where the local variable n points. To reflfect changes outside the function you can pass the parameter by reference:

//             V
void func(int *&n)

And get the expected compiler error, because you can't bind ptr to a non-const reference.

Lukas-T
  • 11,133
  • 3
  • 20
  • 30
  • Now it makes sense.. so when a function receives a pointer as argument, it's actually a copy of it (of the address it holds) and not really the pointer itself? And if so, then in my code the function was called successfully because inside the function `n` is a copy of a non-const pointer? – Itamar Ivri Feb 16 '21 at 18:08
  • 1
    @ItamarIvri Correct, it's the same for arguments of any type in C++. – Lukas-T Feb 16 '21 at 18:19
  • So what exactly makes the difference between `void func(int *&n)` or `void func(int *n)` ? How come in the second one the function treats `n` as a non-const pointer, and in the first one as a const pointer? – Itamar Ivri Feb 16 '21 at 18:38
1

Here int * const ptr=&x; the ptr itself is const, but not the value pointed to (pointee).

When passing ptr to void func(int *n) the value of ptr (= content of ptr == memory address of x) is copied into n. But the pointer type is a pointer to a non-const int in both cases. So no mismatch here.

If on the other hand, the pointee instead would be made const as:

const int * ptr=&x;  // note: placing const before *

then you would get a compilation error as expected, because this would allow func to change a const object.

StPiere
  • 4,113
  • 15
  • 24
  • Then `ptr` == value of ptr == address of non-const int x while `*&ptr`== value of what's inside the address of ptr == a const pointer to non-const int? – Itamar Ivri Feb 16 '21 at 18:22
  • `&ptr` is address of pointer variable itself. so `*&ptr` will be the same as pointer `ptr`, but it has nothing to do with the value pointed to (`*ptr`). – StPiere Feb 16 '21 at 18:32