Why can't I pass a non-const pointer to a function that refers to a pointer to a constant as an argument

Here is a snippet of code that hopefully conveys what I'm trying to do:

void updatePointer(const int*& i) { i++; } int main() { int array[5]; int* arrayPtr = array; updatePointer(arrayPtr ); return 0; } 

This gives a compiler error:

 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 updatePointer(const int*&)' 
+4
source share
3 answers

Suppose you can do this, you can write the following:

 const int c = 0; void updatePointer(const int* &i) { i = &c; } int main() { int *ptr; updatePointer(ptr); *ptr = 1; // attempt to modify the const object c, undefined behavior } 

The purpose of const is to ensure that the user code cannot try to modify the const object if it does not contain const-cast (or the equivalent). Therefore, the compiler must abandon this code. Denying const int*& binding from binding to int* is the only place in the code above that is reasonable for the compiler to refuse: every other line is fine.

For the same reason, you cannot implicitly convert int** to const int ** .

Besides the motivation from the point of view of security const, you might think if in terms of int* is another type from const int* , which is simply converted to it. Similarly, you can convert int to double , but double& cannot bind to an int lvalue value. This is not a complete reason, because actually int* and const int* have the same size and representation, while int and double do not. Thus, there may be a special case to allow him, if not for the fact that he would violate the const system.

The reason C ++ has both const and non-constant overloads for strchr is related to this problem: your updatePointer function changes its input rather than returning an updated value, but the principle is similar. The C-style strchr single allows you to "wash" a pointer to a constant into a pointer to a non-const without cast, and this is a hole in the const system. C ++ (a) has an overload and (b) has a more strict type system than C, so it closes this hole.

If you want your real updatePointer function updatePointer work like strchr - look at the data pointed to and calculate the new value for the pointer, then you are in the same situation as strchr . This is regardless of what it does with the new value (return it in the case of strchr , write it back in the case of updatePointer ), because the problem is that you want the new pointer to have the same const qualification as input. You need to specify either const, or non-constant overload, or a function template.

If you only need your real updatePointer function to move the pointer a certain distance, regardless of the data it points to, you can use std::advance instead.

+6
source

What you wrote is a function referencing a pointer to const int. What you ask for will be

 updatePointer(int* const & i); 

However, this does not make much sense. Passing a reference to a pointer seems to imply that you intend to change the pointer, but you cannot do this because it is declared as const. Be that as it may, you will get the same effect by simply passing the pointer, as in

 updatePointer(int* i); 
+5
source

Found this. Copied here if the connection is broken in the future:

The behavior is a bit uncomfortable to handle this. The main question: Since "const int &" can be bound to "int", why can't "const int * &" be associated with "int *"?

Basically, as soon as you add a level of indirection (pointer), then the rules change. With only one level of indirection (as in one *) a rule can be indicated as:

A reference to a pointer to a cv-qualification type can be tied to the whole type whose qualifications are less than or equal to the value of the pointer (which is a reference). (Read this a few times.)

So, the reason a "const int * &" cannot be attached to "int *", because "const int *" and "int *" are two different types (the underlined part of the rule is broken).

+1
source

Source: https://habr.com/ru/post/1436348/


All Articles