Search code examples
c++constantsstandards

Same object as const and non-const, what should I assume to behave correctly?


I have a function of the form

return_type function(const argument_type & a, argument_type & b);

If the same object is passed as a and b, can I proceed with the function (thereby potentially modifying it) or halt?

I don't have the knowledge about how the compiler assumptions propagate on that case.

My guess is that non-constness assumptions for it being passed as non-const b should suffice and allow the modifications, but it's a guess.


Most answers were about being able to modify a or b, or call non-const methods. I know that if I pass the same object as both const and non-const I can do that. My doubt lies more in state that I'm going to left the program when the function returns, and if it can brake some compiler assumptions, for example:

class A(){
    int value;
}

void function1(const A & arg1);
void function2(A & arg1);
void function3(const A & arg1, A & arg2);

A a;
a.value=5;
function1(a);
if(a.value==5){/*...*/;} // the if can be optimized out to true, because [a] was const

a.value=5;
function2(a);
if(a.value==5){/*...*/;} //must be checked, [a] could have been modified

a.value=5;
function3(a, a);
if(a.value==5){/*...*/;} // ??? 

Most similar question I've found (but not really it)

Modifying self within const method via non const pointer to self


Solution

  • The problem with

    return_type function(const argument_type & a, argument_type & b);
    

    and a call function( o , o ) is that the function probably

    • modifies the object through formal argument b, while

    • at the same time expecting formal argument a to remain unchanged.

    So you will probably break the assumptions of the function, resulting in e.g. incorrect results or a crash.


    There is one function that by design often has this kind of signature, namely the copy assignment operator. Its constant formal argument a is the explicity provided argument, and its mutable formal argument (if one can call it that) is the implicit *this. It can either check for self-reference (aliasing of the arguments) or it can copy and swap.


    In summary, whether you can safely call the function with the same object as argument a and as argument b depends on the function, but chances are that you will violate the function's assumptions, that it has as an implicit precondition that the formal arguments refer to different objects.