Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between "std::string const &s" and "const std::string &s"?

I was looking for examples on how to do something and saw this two variants:

std::string const &s;
const std::string &s;

in different snippets.

thx for your answer :)

like image 721
Thomas Good Avatar asked Mar 10 '16 09:03

Thomas Good


People also ask

What is the difference between std::string and string?

std::string is the string class from the standard C++ library. String is some other string class from some other library. It's hard to say from which library, because there are many different libraries that have their own class called String.

What is const std :: string&?

The data type const string& literally means “a reference to a string object whose contents will not be changed.” There are three ways to pass things around (into and out of functions) in C++: Pass by value - a copy of the original object is created and passed.

What is the difference between string and const char *?

string is an object meant to hold textual data (a string), and char* is a pointer to a block of memory that is meant to hold textual data (a string). A string "knows" its length, but a char* is just a pointer (to an array of characters) -- it has no length information.

Can strings be const?

String constants, also known as string literals, are a special type of constants which store fixed sequences of characters. A string literal is a sequence of any number of characters surrounded by double quotes: "This is a string." The null string, or empty string, is written like "" .


4 Answers

std::string const & is equivalent to const std::string &.

const std::string & is the style adopted in Stroustrup's The C++ Programming Language and probably is "the traditional style".

std::string const & can be more consistent than the alternative:

the const-on-the-right style always puts the const on the right of what it constifies, whereas the other style sometimes puts the const on the left and sometimes on the right.

With the const-on-the-right style, a local variable that is const is defined with the const on the right: int const a = 42;. Similarly a static variable that is const is defined as static double const x = 3.14;. Basically every const ends up on the right of the thing it constifies, including the const that is required to be on the right: with a const member function.

(see What do “X const& x” and “X const* p” mean? for further details).

If you decide to use const-on-the-right style, make sure to don't mis-type std::string const &s as the nonsensical std::string & const s:

The above declaration means: "s is a const reference to a std::string". It's redundant since references are always const (you can never reset a reference to make it refer to a different object).

like image 104
manlio Avatar answered Oct 07 '22 00:10

manlio


Technically it is the same and does not make any difference. But in some debuggers (lldb for sure) you will see std::string const& even if you have written as const std::string&.

like image 25
Khurram Shehzad Avatar answered Oct 07 '22 02:10

Khurram Shehzad


As noted, they're the same type. One reason to like the const on the right is how it plays with templates. Most people process function templates by just substitution. For example:

template <class T> void foo(const T& arg);

int* p;
foo(p);

What is the type of arg? You want to say const int*&, which is to say, a reference to a pointer to const int, but that is wrong. Text substitution has failed you. If you has written it instead like

template <class T> void foo(T const& arg);

Then simple text substitution yields the correct type: int* const&. That is, a reference to const pointer to int.

like image 25
Barry Avatar answered Oct 07 '22 01:10

Barry


As Barry noted in his answer the old C syntax (and the C++ extension of that syntax) doesn't support the conceptual view of text substitution, as in mathematics.

Using the C syntax directly it's therefore generally a good idea to write T const, not const T, even though when T is a simple type these type expressions are equivalent. Writing T const also avoids inconsistency in a multi-level pointer declaration like char const* const p;, where the last const can't be moved. Which exemplifies that the equivalence is only for the base type at the start of a declaration.

Some months ago I started an experiment writing const T, and using that notation consistently. Because that's now possible after C++11, without using macros. To support the consistency I use named type builders like

template< class Some_type >
using Ptr_ = Some_type*;

so that instead of the read-from-right-to-left

char const* const p = something;

I can and do write the ordinary reading direction

const Ptr_<const char> p = something;

It's little bit more verbose, but I now, with some experience using it, think it's worth it (I was not sure about that, it was an experiment).

The main drawback is that while this notation supports type deduction for (function template) function arguments just like direct use of C syntax, it does not support type deduction for auto declarations. Happily, since an initializer can easily be made const, about the only problematic case is reference to array. My pragmatic solution so far has been to use the C (or rather, C++) syntax directly in such cases, but I think this represents a shortcoming of or hole in the language, possibly with some general solution that would make things much easier also in other contexts.

For my current type builders like Ptr_, see the cppx/core_language_support/type_builders.hpp file at Github. They include e.g. In_ for function arguments. And yes, I've found that also worth it, in clarity, in spite of some verbosity, because it makes the intent very clear. However, the cppx stuff is experimental and subject to change. The specific file linked to here may even be moved, but it will be thereabouts. :)

like image 31
Cheers and hth. - Alf Avatar answered Oct 07 '22 00:10

Cheers and hth. - Alf