FString&

Hello, I’m running through the Cows and Bulls game and I’m confused by the following:

void UBullCowCartridge::OnInput(const FString& Input)
{
}

What is the meaning and purpose of the “&” symbol at the end of FString?

Also, why do we need to define this parameter as a constant? How even does this work, as surely the value of “Input” changes multiple times over the course of the game?

Thanks in advance for any replies.

That is explained later.

const doesn’t mean it will never change. It means that once initialised it will never change.

int square(const int n)
{
    //  n = 10; compilation error. can't modify; n is `const`
    return n * n;
}

int main()
{
    // perfectly fine.
    const int four = square(2);
    const int nine = square(3); 
}

Why does const need to be there, rather than just having:

void UBullCowCartridge::OnInput(FString& Input)
{
}

Can you also tell me what the purpose of the “&” is? Why not just have

void UBullCowCartridge::OnInput(const FString Input)
{
}

Hi

The const makes sure that variable Input will not be changed inside of this function. You might want it for different reasons, but here, I believe, it’s needed for making sure that any function, which is called inside of OnInput function and also takes Input as argument, doesn’t change that variable, so every function will handle the same FString and it won’t be accidentally overridden by one of them.

In this case the & means reference to an object. You can google it if you want some detailed info on what reference to an object is and why you should use it, but in short:
if you pass a variable like this const FString Input, a function will make a copy of that variable and operate with this copy, which means that every change will be made to a copy instead of object itself. But if you pass a variable through a reference like this const FString& Input, a function will not make a copy of that variable, so every change will be applied to an object itself.

So, there are 2 main reasons to use references:

  1. If you want to somehow change a variable in a function.
  2. It is faster, as a copy of a variable will not be made.

Because the declaration was const FString&

That it is a reference. As previously stated that is covered later. However if you want to get ahead of yourself continue reading otherwise stop here.


void UBullCowCartridge::OnInput(const FString Input);

This is known as “passing by value” and would mean a copy of the FString. For primitive types this is completely fine and the most performant option as they are cheap to copy. An FString however, is not cheap to copy.

When you create an FString it will dynamically allocate memory in which to store the string (sometimes more than you initially need so you can append more characters to it). At then at the end of its lifetime would need to free that memory.

When you copy it you will have to do the same thing. Allocate enough to store the string and then copy each character over to the new string then free that memory when it goes out of scope.

So for this function to pass by value you would copy the string over, do nothing but read it, then free the memory that was allocated at the end of the function.

If all you need is to read it then const T& lets you do that without copying.

See this example: Compiler Explorer

The passed in value is in fact the same object.

Parameter passing advice: C++ Core Guidelines


To expand on my initial answer

void foo(int);
void foo(const int);

These two declarations (note: not the definition) are in fact the same thing. As from the callers perspective it makes no difference whether the function doesn’t modify their copy or not. Why would the caller care what the definition does with their own copy? The object on the callers side will remain the same regardless.

void foo(int&);
void foo(const int&);

In contrast these two function declarations are different, importantly so. As the first one can modify the object that was passed in.

void foo(int& n)
{
    n = 10;
}
int main()
{
    int value = 25;
    foo(value);
    // value == 10
}

It also means you can’t pass in const variables

void foo(int& n)
{
    // do nothing with n
}
int main()
{
    const int value = 25;
    foo(value); // compilation error
}

Because non-const reference is saying “I will modify” even if it doesn’t actually modify it.

Thanks, I didn’t realise that declaration and definition were two different things.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms