1

Here is an example of what I'm trying to understand:

//no param function
std::string getPassword()
{
    std::string password;

    getline(std::cin, password);

    return password;
}

//param function by ref
std::string getPassword(std::string& password)
{
    getline(std::cin, password);

    return password;
}

//void param function by ref
void getPassword(std::string& password)
{
    getline(std::cin, password)
}

//in main
int main()
{
    std::string password;
    getPassword(password); //using void function

    //OR

    password = getPassword(); //using no param function

    //OR

    password = getPassword(password); //using param function

    return 0;
}

Which one of these would be the best way to retrieve a password? Especially, if we're talking large scale like signing on to Netflix for example. I know this code is probably written differently in a professional environment but this is just a basic example to get my point across. I can't seem to find any post about this question so I thought I'd ask. I know the difference between returning by value/ref and returning void (it doesn't return a value) so no worries there.

***EDIT Is it an issue that the address of the string variable in main is different from the local one in the first function? (If you decide the first function is best that is)

Thank you to those that help!

  • 3
    I think this question is a matter of opinion. In my opinion, the first function is the right one. In/out parameters or out parameters should be the second choice (only to be used when they *have* to be used (like in `ostream& operator<<(ostream&, Foo const&);` where the ostream in/out parameter is mutated with the streamed output *and* it is also returned), with a strong preference for return values instead. – Eljay Dec 23 '20 at 12:18

1 Answers1

0

std::string getPassword() is the best way. It is just as efficient as using a reference parameter, thanks to return value optimization. In fact, it could even be more efficient since there is only a limited amount of parameters that can be passed via registers, so if you have a function that takes many parameters, it's best to avoid adding yet another one for passing the result back.

Furthermore, this form allows for composition, for example if you only need the hash of a password, you could write:

auto hash = make_hash(getpassword());

Whereas if you return it via a parameter, you would have to write three lines of code:

std::string password; // can't use auto here!
getpassword(password);
auto hash = make_hash(password);

Another benefit is that you can mark the return value with the [[nodiscard]] attribute in C++17, so you will get a compiler warning if you write something like:

getpassword();

Finally, there are types that either cannot be assigned to, or that cannot be named (like the type of a lambda function), which you can return using the return value, but which you cannot pass back using a reference parameter.

G. Sliepen
  • 7,637
  • 1
  • 15
  • 31
  • Thank you for your answer! It's very helpful. I have one thing to add. If I use the first function then the address of the string variable that's in main is different than the local one to the function. Is that an issue? – Hernan Teran Dec 23 '20 at 12:39
  • RVO is not always possible, but it should in your example. See [this result](https://godbolt.org/z/93Ehnn) for similar code. – G. Sliepen Dec 23 '20 at 13:19