The strings topic in the SO Documentation used to say, in the Remarks section:
Since C++14, instead of using
"foo"
, it is recommended to use"foo"s
, ass
is a string literal, which converts theconst char *
"foo"
tostd::string
"foo"
.
The only advantage I see using
std::string str = "foo"s;
instead of
std::string str = "foo";
is that in the first case the compiler can perform copy-elision (I think), which would be faster than the constructor call in the second case.
Nonetheless, this is (not yet) guaranteed, so the first one might also call a constructor, the copy constructor.
Ignoring cases where it is required to use std::string
literals like
std::string str = "Hello "s + "World!"s;
is there any benefit of using std::string
literals instead of const char[]
literals?
The advice to use
"blah"s
has nothing to do with efficiency and all to do with correctness for novice code.C++ novices who don't have a background in C, tend to assume that
"blah"
results in an object of some reasonable string type. For example, so that one can write things like"blah" + 42
, which works in many script languages. With"blah" + 42
in C++, however, one just incurs Undefined Behavior, addressing beyond the end of the character array.But if that string literal is written as
"blah"s
then one instead gets a compilation error, which is much preferable.strlen
to compute the length. The compiler already knows it.If you're part of the "Almost Always Auto" crowd, then the UDL is very important. It lets you do this:
And thus,
str
will be a genuinestd::string
, not aconst char*
. It therefore permits you to decide when to do which.This is also important for auto return type deduction:
Or any form of type deduction, really:
Copy-elision is not faster than the constructor call. Either way, you're calling one of the object's constructors. The question is which one:
This will provoke a call to the constructor of
std::string
which takes aconst char*
. But sincestd::string
has to copy the string into its own storage, it must get the length of the string to do so. And since it doesn't know the length, this constructor is forced to usestrlen
to get it (technically,char_traits<char>::length
, but that's probably not going to be much faster).By contrast:
This will use the UDL template that has this prototype:
See, the compiler knows the length of a string literal. So the UDL code is passed a pointer to the string and a size. And thus, it can call the
std::string
constructor that takes aconst char*
and asize_t
. So there's no need for computing the string's length.The advice in question is not for you to go around and convert every use of a literal into the
s
version. If you're fine with the limitations of an array ofchar
s, use it. The advice is that, if you're going to store that literal in astd::string
, it's best to get that done while it's still a literal and not a nebulousconst char*
.In addition, UDL makes it easier to have
\0
in the string