C++: const reference, before vs after type-specifier

95,476

Solution 1

No difference as const is read right-to-left with respect to the &, so both represent a reference to an immutable Fred instance.

Fred& const would mean the reference itself is immutable, which is redundant; when dealing with const pointers both Fred const* and Fred* const are valid but different.

It's a matter of style, but I prefer using const as a suffix since it can be applied consistently including const member functions.

Solution 2

Behavior

There is no semantic difference between const T& and T const&; the language treats them as the same type. (The same thing applies to const T* and T const*.)

As a matter of style

Regarding which you should prefer stylistically, however, I'll dissent from a lot of the other answers and prefer const T& (and const T*):

  • const T& is the style used in Stroustrup's The C++ Programming Language book.
  • const T& is the style used in the C++ standard itself.
  • const T* is the style used in K&R's The C Programming Language book.
  • const T* is the style used in the C standard.
  • Due to the above factors, I think const T&/const T* have way more inertia than T const&/T const*. const T&/const T* empirically seem way more common to me than T const&/T const* in all of the C++ and C code that I've seen. I think following common practices is more readable than dogmatically adhering to right-to-left parsing rules.
  • With T const*, it seems easier to misplace the * as T* const (especially if people aren't as accustomed to it). In contrast, const* T is not legal syntax.

What about the right-to-left parsing rule?

Regarding the whole right-to-left parsing argument that people seem to love to use: as I mentioned in a comment to another answer, const T& reads fine right-to-left too. It's a reference to a T constant. "T" and "constant" each can work as an adjective or a noun. (Additionally, reading T const* right-to-left can be ambiguous since it could be incorrectly interpreted as "pointer constant to T" instead of as "pointer to constant T".)

Solution 3

Though they are one and the same, to retain consistency with the RIGHT-LEFT rule about parsing C and C++ declarations, it is better to write Fred const &arg

Also refer this for developing more understanding about declarations, qualifiers and declarators.

Solution 4

Both work, and here is the explanation from the man who wrote it.
To quote him:

Why? When I invented "const" (initially named "readonly" and had a corresponding "writeonly"), I allowed it to go before or after the type because I could do so without ambiguity.

Solution 5

No difference, both are syntactically and semantically same.

Share:
95,476

Related videos on Youtube

eisbaw
Author by

eisbaw

Updated on October 26, 2020

Comments

  • eisbaw
    eisbaw over 3 years

    What is the difference between the arguments in:

    int foo1(const Fred &arg) {
    ...
    }
    

    and

    int foo2(Fred const &arg) {
    ...
    }
    

    ? I don't see this case covered in the parashift FAQ.

    • Oliver Charlesworth
      Oliver Charlesworth over 13 years
    • LatinSuD
      LatinSuD over 13 years
      is this a question about style? "const Fred" sounds good in english, but "Fred const" looks better to me.
    • Frank
      Frank over 13 years
      On a related note, is there any reason one should prefer Fred const &arg over Fred const& arg? I like the latter better because const& is a unit there meaning "constref", and the name arg is separated by a blank from all the type specifiers.
    • Cedric H.
      Cedric H. over 13 years
      @dehmann: But int const& ref doen't mean 'const ref' but 'ref to const'.
    • Michael Aaron Safyan
      Michael Aaron Safyan over 13 years
    • Gunther Struyf
      Gunther Struyf almost 8 years
      @OliverCharlesworth link is broken, I believe it moved to here: isocpp.org/wiki/faq/const-correctness#const-ref-alt
  • Matthieu M.
    Matthieu M. over 13 years
    I prefer the suffix, because it works better with typedef expansion. Example: typedef int* pointer;, const pointer is not const int*, it's int* const. The suffix form is not awkward.
  • jamesdlin
    jamesdlin over 13 years
    IMO const T& reads fine right-to-left too; it's a reference to a T constant. T and constant each can work as an adjective or a noun.
  • Andreas Magnusson
    Andreas Magnusson over 13 years
    +1, agreed. When reading code it's easier to spot a const if the line begins with const. The right-left rule is really only needed when manually parsing especially hairy type declarations. Why not optimize for the most common case? Besides, IMHO if you write type declarations so you need to manually run an FSM in your head you're doing it wrong.
  • ulidtko
    ulidtko about 11 years
    -1. Regardless of how justified your conclusions are and how much I personally agree to them, they are not answering the asked question directly. This makes the second-most answer to a simple question appear like an off-topic gibberish about some messy underwater machinery, with no conclusions, no direct answer — nothing. You'll get my upvote when you add a simple clear summary stating "No, there is no semantic difference between both syntaxes, but there are some stylistical considerations as follows...". And only then all those bullets.
  • abyss.7
    abyss.7 about 5 years
    Then what is a point to make std::is_const<const T&>::value be false?
  • Sean Fausett
    Sean Fausett about 5 years
    @abyss.7 that's a reference to const T; the reference is mutable.
  • pooya13
    pooya13 about 5 years
    IMO the reason const T& reads better, is that: 1- We read code from left to right. And 2- When describing a new concept we start from the more general concept to the more specific. Here, the const keyword is more general as it sections the variable space into two categories, whereas the type specifier sections it into many.
  • Dexter
    Dexter almost 4 years
    "pointer to" should stay together. So there is no ambiguity for T const*
  • jamesdlin
    jamesdlin over 3 years
    @Dexter While "pointer to" should stay together, it's another thing to remember and potentially get wrong.
  • Violet Giraffe
    Violet Giraffe over 3 years
    How is the reference mutable if, by definition, it cannot be re-bound, and this is exactly what is discussed by this question and the answers to it - the notion of T& const being redundant? It was a very valid question about is_const, and one I also would like to know the answer to.
  • Sean Fausett
    Sean Fausett over 3 years
    @VioletGiraffe indeed the reference cannot be re-bound so in that sense references are not mutable. It would be better to simply say that references ignore const qualifiers on the reference itself: "Reference types cannot be cv-qualified at the top level; there is no syntax for that in declaration, and if a qualification is added to a typedef-name or decltype specifier, or type template parameter, it is ignored." (See cppreference.com)
  • Admin
    Admin over 2 years
    @jamesdlin what is there exactly to remember? You read it left to right, as it is written. pointer to const T. Meanwhile const T* has something to remember, the fact that const, if there's nothing on the left, applies to the right, and now tell me, is it constant pointer to T, or is it constant T? How far to the right does const extend to? Why does it go left to right in the first place, against everything else? If we go backwards, then we go backwards all the way. Otherwise you have something to actually remember, because its not as obvious as just reversing a direction.
  • jamesdlin
    jamesdlin over 2 years
    @Sahsahae Huh? 1. T const* is not read left-to-right as written. You have to read it right-to-left, and as I already explained, you have to remember that it's "pointer to constant T" and not "pointer constant to T". 2.Regarding your "meanwhile" remark, as I also already explained in my answer, you do read const T* right-to-left (i.e., "backwards all the way"): "pointer to T constant".
  • Admin
    Admin over 2 years
    @jamesdlin you don't have to remember anything, you literally only need to connect * -> const -> T. That's what reading right to left means. If you mean you have to unlearn that const associates with right instead of left sometimes, well that's the problem of the opposite way of writing it, which is what causes const to apply to the right, because there's nothing on the left const T*, that's why they're unambiguously equal, except harder to grok to people who don't know the rules. and fail to read this whether they read from left or from right. C++ is read right to left otherwise...