std::string s or std::string &s

All is in the question. I understand the main principle, but I am wondering why often coders prefer the second way. The both seems legits, but there is some pertinence here no?

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>

void f(const std::string &s) { std::cout << s << std::endl; }
// void f(const std::string s) { std::cout << s << std::endl; }

int main()
{
    const std::string s = "Single line";
 // const std::string &s = "Single line";
    f(s);
}
Last edited on
The & as part of the function parameter signature is to pass the object by reference.
https://www.learncpp.com/cpp-tutorial/pass-by-lvalue-reference/

Without & the object's value is copied and that copy is passed into the function.
https://www.learncpp.com/cpp-tutorial/introduction-to-function-parameters-and-arguments/
its probably mentioned in the links but copying anything bigger than a pointer is more expensive than not copying it. Strings are generally bigger than pointers.
Last edited on
line 9 creates a temporary, the actual object referred to isn't named and will be deleted when the compiler decides it's no longer used. It's no an alternative to line 8 in most cases.
Consider std::string_view as an alternative for std::string const&

Otherwise the advice is the same in general.
See:
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#f15-prefer-simple-and-conventional-ways-of-passing-information
By reference instead of copy. Thanks for all your answers and links.

So if the parameter is bigger than 32 bits (or 64 according to the OS) it is better to pass the object by its reference?
Last edited on
yes, or as I said, whatever a pointer is on your machine really -- that may be 256 bits one day.
> So if the parameter is bigger than 32 bits (or 64 according to the OS)
> it is better to pass the object by its reference?

How a parameter should be passed to a function is governed by design intent.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct X { /* ... */ };

// the function wants a copy of the object and assumes ownership of the copied object
void foo( X ) ;

// the function wants to inspect the caller's object, but it won't (can't) modify it
void foo( const X& ) ;

// the function may (usually would) modify the caller's object
// (on return, the caller's object would be in a well-defined and well-specified state)
void foo( X& ) ;

// the function may (usually would) move from the caller's object
// (on return, the caller's object would be in a well-defined, but unspecified state)
void foo( X&& ) ;

// the function is not in itself interested in the const-ness or value category of the argument 
// anything would do; but it wants to be able to pass it correctly (forward) to other functions 
template < typename T > void foo( T&& ) ;
So if the parameter is bigger than 32 bits (or 64 according to the OS) it is better to pass the object by its reference?


1) Unless it is required that any changes to the object are changed back in the caller, then pass by const ref - not ref.

2) If a copy of the object is required, then pass by value. This is often used in eg a class operator=() member function or when only local changes are required.

3) Don't forget std::move and pass by ref-ref (&&) as appropriate.
Last edited on
kbw wrote:
line 9 creates a temporary, the actual object referred to isn't named and will be deleted when the compiler decides it's no longer used. It's no an alternative to line 8 in most cases.

Binding a const ref directly to a temporary like that extends the lifetime of the temporary. The temporary won't get destroyed until the reference goes out of scope.
I posted a simple question - but what amazing answers! Thanks ++
I posted a simple question


In C++, that's almost an oxymoron!
Topic archived. No new replies allowed.