2

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?

Community
  • 1
  • 1
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • A move semantics overload might be useful only if you need to store the value of `path` somewhere for later. – aschepler Jan 12 '13 at 17:51
  • 2
    @LightnessRacesInOrbit Why is this question being closed as a duplicate of a question asked ~4 years ago? That question's answer completely ignores move semantics and references Effective C++, which gives guidance purely on C++98 best-practices. If this is the case, why is Scott bothering to update the book and its recommendations for C++11? – Bret Kuhns Jan 12 '13 at 18:06

3 Answers3

5

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.
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • Does this also apply to types like int, float? Does this have any effect with C++11 move semantics? – Vittorio Romeo Jan 12 '13 at 17:47
  • @alok I would add, that this doesn't apply to fundamental data types such as int where it is cheaper to pass by value. – JBentley Jan 12 '13 at 17:48
  • @Vee: Any good commercial compiler should be able to optimize the copy being made for in-built data types. – Alok Save Jan 12 '13 at 17:49
  • @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. – Alok Save Jan 12 '13 at 17:51
  • 2
    [Not everybody agree with you](http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/) – Lol4t0 Jan 12 '13 at 17:51
  • 1
    @Lol4t0: Check for Timo's comment on Bret's answer. – Alok Save Jan 12 '13 at 17:53
  • @AlokSave, I agree that passing by refernce is common case, but not **_italic bold golden rule_** – Lol4t0 Jan 12 '13 at 17:57
  • 1
    @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? – JBentley Jan 12 '13 at 17:57
  • 1
    @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. – Benjamin Lindley Jan 12 '13 at 17:57
  • 1
    @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. – Lol4t0 Jan 12 '13 at 18:02
  • 1
    @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. – Alok Save Jan 12 '13 at 18:06
4

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).

Timo Geusch
  • 24,095
  • 5
  • 52
  • 70
  • I wouldn't be so sure that passing a reference avoids memory allocations. – Lightness Races in Orbit Jan 12 '13 at 17:52
  • 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. –  Jan 12 '13 at 17:55
  • 1
    @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. – JBentley Jan 12 '13 at 18:21
1

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.

Bret Kuhns
  • 4,034
  • 5
  • 31
  • 43
  • In this situation probably `T const&` is better. – Nawaz Jan 12 '13 at 17:49
  • 2
    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. – Bret Kuhns Jan 12 '13 at 17:50
  • 3
    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. – Timo Geusch Jan 12 '13 at 17:51
  • @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. – Bret Kuhns Jan 12 '13 at 17:52
  • 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. – Yakov Galka Jan 12 '13 at 17:52
  • 1
    @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. – Bret Kuhns Jan 12 '13 at 17:54