C++: const reference, before vs after type-specifier
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 thanT const&
/T const*
.const T&
/const T*
empirically seem way more common to me thanT 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*
asT* 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.
Related videos on Youtube
eisbaw
Updated on October 26, 2020Comments
-
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 over 13 years
-
LatinSuD over 13 yearsis this a question about style? "const Fred" sounds good in english, but "Fred const" looks better to me.
-
Frank over 13 yearsOn a related note, is there any reason one should prefer
Fred const &arg
overFred const& arg
? I like the latter better becauseconst&
is a unit there meaning "constref", and the namearg
is separated by a blank from all the type specifiers. -
Cedric H. over 13 years@dehmann: But
int const& ref
doen't mean 'const ref' but 'ref to const'. -
Michael Aaron Safyan over 13 yearsDuplicate of: stackoverflow.com/questions/2640446/…
-
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. over 13 yearsI prefer the suffix, because it works better with
typedef
expansion. Example:typedef int* pointer;
,const pointer
is notconst int*
, it'sint* const
. The suffix form is not awkward. -
jamesdlin over 13 yearsIMO
const T&
reads fine right-to-left too; it's a reference to a T constant.T
andconstant
each can work as an adjective or a noun. -
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 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 about 5 yearsThen what is a point to make
std::is_const<const T&>::value
befalse
? -
Sean Fausett about 5 years@abyss.7 that's a reference to
const T
; the reference is mutable. -
pooya13 about 5 yearsIMO 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, theconst
keyword is more general as it sections the variable space into two categories, whereas the type specifier sections it into many. -
Dexter almost 4 years"pointer to" should stay together. So there is no ambiguity for
T const*
-
jamesdlin over 3 years@Dexter While "pointer to" should stay together, it's another thing to remember and potentially get wrong.
-
Violet Giraffe over 3 yearsHow 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 aboutis_const
, and one I also would like to know the answer to. -
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 over 2 years@jamesdlin what is there exactly to remember? You read it left to right, as it is written.
pointer to const T
. Meanwhileconst 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 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 readconst T*
right-to-left (i.e., "backwards all the way"): "pointer to T constant". -
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 leftconst 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...