Search code examples
c++constantspass-by-value

In C++, why doesn't the copy of a constant also have to be a constant when I pass it by value?


For example, this code compiles (g++ 13.1.0) and gives me output "Sum is 20":

#include <iostream>

using namespace std;

void add (int x, int y, int sum);

int main(){
    int x = 10, y = 10;
    const int sum = 0;

    add (x, y, sum);

    return 0;
}

void add (int x, int y, int sum) {
    sum = x + y;
    cout << "Sum is " << sum << endl;
}

I expected the compiler to complain about either trying to pass a constant value to something that's treated as non-constant within the function, or failing to declare sum as constant in add. I think I understand everything that's happening here - I'm creating a non-constant copy of a constant variable. I'm just curious why this kind of behavior is permitted.


Solution

  • I think I understand everything that's happening here - I'm creating a non-constant copy of a constant variable.

    No and no.

    You're copying/assigning the value of a constant variable into a non-constant variable, which is totally ok, e.g.

    const int c = 0; //constant variable, define/initialize it
                     //with the value 0
    int i = c; //declare non-constant variable and define/initialize it
               //with the value of c
    
    //or
    
    int i; //declare only
    i = c; //assign/copy value of c to i
    

    Even this is valid

    int i = 0;
    const int c = i;
    
    //but
    
    i = 42; //ok
    c = 42; //not ok, c is read only
    

    Passing arguments by value to a function is not indifferent to declaring a variable and assigning a value to it. The function argument is local to the function and if it is declared as non const, it can be freely modified.

    e.g.

    void foo(int sum)
    {
        sum = 42; //ok, sum is a local non constant variable
    }
    
    const int c = 0;
    foo(c); //assign/copy the value of c to the variable sum, same as:
            //int sum = c;
    

    but

    void foo(const int sum)
    {
        sum = 42; //not ok, sum is a local constant variable, 
                  //read only -> not modifiable
        //but
        int i = sum;
        i += 1; //ok, i is modified not sum
    }
    
    int i = 0;
    foo(i); //ok, assign/copy the value of i to the variable sum, same as:
            //const int sum = i;
    
    const int c = 0;
    foo(c); //ok, assign/copy the value of c to the variable sum, same as:
            //const int sum = c;
    

    In short: the const type qualifier is a promise to the compiler, that once the variable is initialized to never be modified again. And the compiler will let you know (via error) if you do so. But once copied into other variables, there might be no promise for those regions of memory (if non const).