Search code examples
c++referencepass-by-referenceinlinedereference

Do inlined pass-by-reference functions still create reference variables?


I am writing a loop that has some state variables.

int MyFunc(){
    int state_variable_1 = 0;
    int state_variable_2 = 12;

    while(state_variable_1 != state_variable_2){
        BodyOfWhileLoop(state_variable_1, state_variable_2);
    }
}

As you can see, I have written the body of the while loop in a separate function, BodyOfWhileLoop. This is to keep the code clean and to aid in debugging.

BodyOfWhileLoop will need to modify state_variable_1 and state_variable_2. I could pass these by reference, for example,

void BodyOfWhileLoop(int& state_variable_1, int& state_variable_2);

This is functionally exactly what I want, however, each use of the state variables in the body of the function requires a dereference (I believe). I could do something like this:

void BodyOfWhileLoop(int& state_variable_1_ref, int& state_variable_2_ref){
    int state_variable_1_copy = state_variable_1_ref; 
    int state_variable_2_copy = state_variable_2_ref; 

    // Do stuff with state variables
    
    state_variable_1_ref = state_variable_1_copy; 
    state_variable_2_ref = state_variable_2_copy; 
}

I see two things to be true:

  1. Copying the state variables costs memory since you allocate space for the copy.
  2. Not copying the state variables will cost time because there is an extra dereference in the body of BodyOfWhileLoop each time you access the state variable.

So I have two questions:

  1. If the compiler inlined BodyOfWhileLoop, would it still create a state_variable_1_ref and state_variable_2_ref (requiring a dereference to access the ints)? Would the cost of accessing state_variable_1 be the same as accessing it within MyFunc?
  2. Are there alternative solutions I have not seen?

Solution

  • No, they do not. Demonstration: https://godbolt.org/z/qc1ne7ezM.

    References are typically implemented as pointers under the hood (though they do not have to be). Once the function is inlined the compiler will eliminate the indirection. In LLVM, this optimization is performed as part of SROA.

    Any function with only one callsite should be inlined by the optimizer but note that if a function has external linkage the compiler may not inline it: It could be used in other translation units so the compiler doesn't know it's only used once. To avoid this, mark it static or inline, or use link-time optimization.