Pass arguments as std::string or const std::string&?

10,734

Solution 1

The canonical answer in your situation would be to pass the argument by const&, both for reasons of performance (it is guaranteed to avoid copying the string) and because you document intent. The former is only important if you have profiled your code and determined that passing the string is a bottleneck - if it isn't, you're mostly looking at "best practises" rather than making a big performance difference.

However to me, if I look at the signature of your function, the second one clearly states "I will only read your parameter and not do anything to it", whereas the first one pretty much states that you will be doing something to the parameter, even though your changes will not be visible to the outside as you are working on a copy of the parameter.

There is also the added advantage that passing the argument by const reference avoids memory allocations, which is handy if you are working on a system that doesn't have infinite memory (ie, all of them).

Solution 2

Golden Rule:

"Always Pass by const reference by default."

This should be your default choice when passing function arguments. You chose other options as per the situation demands.

  • It is always more efficient for custom classes.
  • It is more intuitive to the user.

Solution 3

You're likely better off with the by-value parameter. See this post, Want Speed? Pass by Value, for detailed reasons. Basically, you give the caller and/or compiler more flexibility in how your function can be called. Using const& enforces what used to be a C++98 best-practice, but can work against move semantics in C++11.

Share:
10,734
Vittorio Romeo
Author by

Vittorio Romeo

I write code, lift weights and play games. I also like everything sci-fi.

Updated on June 05, 2022

Comments

  • Vittorio Romeo
    Vittorio Romeo almost 2 years

    Possible Duplicate:
    Is it better in C++ to pass by value or pass by constant reference?

    I thought about this while writing a file system.

    vector<string> getFiles(string path);
    vector<string> getFiles(const string& path);
    

    What one is faster? What one is more elegant?

    Obviously path will never be changed in the getFiles method.

    Bonus: I'm using C++11. Is there a way move semantics would speed everything up?

  • Vittorio Romeo
    Vittorio Romeo over 11 years
    Does this also apply to types like int, float? Does this have any effect with C++11 move semantics?
  • JBentley
    JBentley over 11 years
    @alok I would add, that this doesn't apply to fundamental data types such as int where it is cheaper to pass by value.
  • Nawaz
    Nawaz over 11 years
    In this situation probably T const& is better.
  • Alok Save
    Alok Save over 11 years
    @Vee: Any good commercial compiler should be able to optimize the copy being made for in-built data types.
  • Bret Kuhns
    Bret Kuhns over 11 years
    I would agree if the intent is to only read the string. If the function is going to internally copy the const& anyway, then by-value is the best choice in C++11.
  • Alok Save
    Alok Save over 11 years
    @JonBentley: True it doesn't have to for fundamental types but only because the compiler can apply optimizations, Doesn't hurt to follow the same rule.
  • Lol4t0
    Lol4t0 over 11 years
  • Timo Geusch
    Timo Geusch over 11 years
    Your linked article addresses a couple of very specific uses of the parameter, though - namely ones where the parameter that is being passed in is manipulated inside the function and returned back out. There is a good chance that in the context of the OP's question, this is not the case.
  • Lightness Races in Orbit
    Lightness Races in Orbit over 11 years
    I wouldn't be so sure that passing a reference avoids memory allocations.
  • Bret Kuhns
    Bret Kuhns over 11 years
    @TimoGeusch fair enough. I made the assumption that the OP was providing an example that spurred his question, but was looking for a more generalized answer.
  • Yakov Galka
    Yakov Galka over 11 years
    I would argue that deciding what the interface is based on the implementation (whether the implementation of the function copies it or not) is all wrong.
  • Alok Save
    Alok Save over 11 years
    @Lol4t0: Check for Timo's comment on Bret's answer.
  • Bret Kuhns
    Bret Kuhns over 11 years
    @ybungalobill Not necessarily. I didn't mean this in a performance sense, but in a way to convey information. const& really says "I want to look at this" when reading a function declaration. If the function then copies internally, then the declaration is misleading.
  • Admin
    Admin over 11 years
    The apparent intent when taking a reference parameter is because you want your function to see changes to the argument that take place while the function is executing. (Say, a global variable is passed by reference to a function that also accesses that global variable directly. Regardless of whether global variables are good or bad.) Knowing what const & is really used for, it is obvious enough, but I would never advocate it for readability.
  • Lol4t0
    Lol4t0 over 11 years
    @AlokSave, I agree that passing by refernce is common case, but not italic bold golden rule
  • JBentley
    JBentley over 11 years
    @Alok it is better IMO to write sound code in the first place than to rely on the compiler to improve your code for you. Your commercial compiler might perform the optimization, but what about some other user of your code? Do you want your code's performance being dependent on some specific compiler?
  • Benjamin Lindley
    Benjamin Lindley over 11 years
    @Lol4t0: Who? Not the author of that article. That article is about copy elision, which doesn't likely do anything useful here. Either the function recieves an R-value, and no copy is made in either case. Or the function recieves an L-value, in which case, it has to be copied if it takes its parameter by value, but not if it takes it by reference. Copy elision is useful when you need a copy anyway, but no copy is needed here.
  • Lol4t0
    Lol4t0 over 11 years
    @BenjaminLindley, it is not clear, if copy is needed, and if it will be needed tomorrow, when it will be to late to change the interface. My point is that you should not call smth golden rule to make people follow your rule without thinking.
  • Alok Save
    Alok Save over 11 years
    @Lol4t0: Your objection is pretty much perception based. Yes, You should always pass by const reference by default unless the situation demands otherwise & I have explicitly stated so. If it does not fit your perception then I cannot help it. The answer stays as is because there is nothing wrong in it.
  • JBentley
    JBentley over 11 years
    @Timo Just to add something further, profiling may indicate that your application doesn't have a bottleneck with passing strings by value, but someone else's use of your code (or your own future use) might incur more time spent copying strings than you planned for (perhaps the user calls getFiles repeatedly with long path names, in the OP's example) - hence it's a good idea to follow "best practices" even if you don't think it affects you right now, unless there is some reason not to.