mbr_uk
mbr_uk

Reputation: 53

Passing values as reference and "const" values

After some years without touching c++, I am getting back at it and decided to study again using a text book ("Sutherland, Bruce. Learn C++ for Game Development (p. 59). Apress. Kindle Edition."). I have 2 quick questions:

1) In one example, the book uses the following lines of code to call a function:

string playerInput; 
GetPlayerInput( playerInput);

And the function itself is defined as:

void GetPlayerInput(string& playerInput) 
{ 
    cin >> playerInput; 
} 

Question: The "playerInput" being passed as "string&". Is it really necessary? Why is this being passed as reference when we could just make the function return a string and do it like this:

string playerInput; 
playerInput = GetPlayerInput();

And:

string GetPlayerInput() 
{ 
    cin >> playerInput; 
    return playerInput;
}

Is this just a stylistic choice or I am missing something here?

2) An class accessor method to get a user name was defined as:

'void SetName(const std::string& name);'

No other explanation. What's up with this "const" thing? I did some research but only got more confused. Why would you need it when passing a string as a parameter (and again as reference??)

Thank you so much for any help!

Upvotes: 0

Views: 105

Answers (2)

EmDroid
EmDroid

Reputation: 6066

1) In principle, returning by value involves a copy. Nevertheless, virtually all compilers perform RVO/NRVO even in the debug mode.

So in general it is an API choice, however it can be significant if used in the loop. Compare the two, for example:

for (;;) {
    string playerInput = GetPlayerInput();
    if (playerInput.empty()) break;
    // do something with the playerInput
}

string playerInput;
for (;;) {
    GetPlayerInput(playerInput);
    if (playerInput.empty()) break;
    // do something with the playerInput
}

There is a subtle difference, which makes the later case much more performant. In the first case, even with NRVO, the string is newly allocated each time. In the second case, on the contrary, the string is only allocated/reallocated a few times and at the end it has the size of the longest input.

Also, the GetPlayerInput could then return bool, which would make the loop much better looking:

string playerInput;
while (GetPlayerInput(playerInput)) {
    // do something with the playerInput
}

2) Passing by const ref (as opposed to non-const ref) not only makes it impossible to modify the parameter by mistake, but also makes it possible to use temporaries, which is arguably even more important. As an example:

setName("Some name");

does not work with non-const reference.

When passing by value, there is again a copy involved - it might be elided (it is allowed in C++, which has the downside that code relying on copying might not work), but it is not guaranteed (and only works when passing temporaries btw.).

The only case where it is advisable to use pass by value is when you would copy the parameter internally anyway, like for example:

SomeClass operator +(SomeClass a, const SomeClass& b) {
    return a += b;
}

contrary to

SomeClass operator +(const SomeClass& a, const SomeClass& b) {
    SomeClass result = a;
    return result += b;
}

Upvotes: 1

Dreamer
Dreamer

Reputation: 112

It totally depends on the programmer whether to pass by reference or by value. If you're talking about passing by reference, the changes will be made in the original value of the variable whereas, if you use passing by value a copy of actual arguments is passed to formal arguments of the called function. So, you can do both!

Upvotes: 0

Related Questions