30

My co-worker is 0 for 2 on questions he has inspired (1, 2), so I thought I'd give him a chance to catch up.

Our latest disagreement is over the style issue of where to put "const" on declarations.

He is of the opinion that it should go either in front of the type, or after the pointer. The reasoning is that this is what is typically done by everyone else, and other styles are liable to be confusing. Thus a pointer to a constant int, and a constant pointer to int would be respectively:

const int *i;
      int * const i;

However, I'm confused anyway. I need rules that are consistent and easy to understand, and the only way I can make sense of "const" is that it goes after the thing it is modifying. There's an exception that allows it to go in front of the final type, but that's an exception, so it's easier on me if I don't use it.

Thus a pointer to a constant int, and a constant pointer to int would be respectively:

int const * i;
int * const i;

As an added benefit, doing things this way makes deeper levels of indirection easier to understand. For example, a pointer to a constant pointer to int would clearly be:

int * const * i;

My contention is that if someone just learns it his way, they'll have little trouble figuring out what the above works out to.

The ultimate issue here is that he thinks that putting const after int is so unspeakably ugly, and so harmful to readability that it should be banned in the style guide. Of course, I think if anything the guide should suggest doing it my way, but either way we shouldn't be banning one approach.

Edit: I've gotten a lot of good answers, but none really directly address my last paragraph ("The ultimate issue"). A lot of people argue for consistency, but is that so desirable in this case that it is a good idea to ban the other way of doing it, rather that just discouraging it?

T.E.D.
  • 44,016
  • 10
  • 73
  • 134
  • 1
    Another important point is, what is more important? The fact that it's an int, or the fact that it's constant? – rlbond Jun 12 '09 at 18:22
  • @rlbond: That's a good question...so good I'm not sure I can answer it. – T.E.D. Jun 12 '09 at 18:29
  • @T.E.D. Regarding your edit: what's the point of the style guide? Is it a suggestion that developers are to ignore at their leisure, or is it a rule that they are expected to follow? If you simply discourage particular style, then wouldn't that mean it's a suggestion? – atk Nov 13 '09 at 23:00
  • @atk: In this case, I believe it is the latter. – T.E.D. Nov 16 '09 at 15:24
  • @T.E.D. Why did you asked the question in a C++ context only? I see no differences to C here. – RobertS supports Monica Cellio Feb 07 '20 at 16:24
  • @T.E.D. Furthmore, This is a good question but did not had an appropriate title. I could not even found that question with keywords in the search; I only came here by accident from your link in your answer https://stackoverflow.com/a/1143418/12139179 to [What is the difference between const int*, const int * const, and int const *?](https://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-and-int-const/60115415#60115415). So I´ve chosen a better title, that people can find this question way more efficiently. – RobertS supports Monica Cellio Feb 07 '20 at 16:28

15 Answers15

55

The most important thing is consistency. If there aren't any coding guidelines for this, then pick one and stick with it. But, if your team already has a de facto standard, don't change it!

That said, I think by far the more common is

const int * i;
int * const j;

because most people write

const int n;

instead of

int const n;

A side note -- an easy way to read pointer constness is to read the declaration starting at the right.

const int * i; // pointer to an int that is const
int * const j; // constant pointer to a (non-const) int
int const * aLessPopularWay; // pointer to a const int
DevSolar
  • 67,862
  • 21
  • 134
  • 209
rlbond
  • 65,341
  • 56
  • 178
  • 228
  • I disagree with "That said, I think by far the more common is". Otherwise agree. – Martin York Jun 12 '09 at 18:05
  • 4
    Do you think more people do it the other way? Personally, I've seen const type* much more often. – rlbond Jun 12 '09 at 18:10
  • 15
    Well - not the most scientific result, however, google code search has 41 results 'int const *' and 824 for 'const int *' (searching with lang:c++) – Richard Corden Jun 12 '09 at 18:17
  • 1
    Consistency is not so important, more important is flexibility and diversity. – Brent Bradburn Nov 13 '09 at 03:35
  • @nobar: Consistency is important when there are 2 identical ways of doing something. – rlbond Nov 13 '09 at 06:02
  • @ribond: It appears that we are at odds about consistency and pointers but we agree on one thing: "I like C++." on our "About Me" pages. :) – Brent Bradburn Nov 13 '09 at 16:29
  • 2
    @finnw: I always marvel at why people insist that the `*` must be adjacent to anything. Write `int * i;`, and not only will neither of the two "camps" blame you for favoring the other's view, but the chance of anyone overlooking the `*` is actually less than with *either* of the alternatives. – DevSolar Jul 14 '10 at 15:35
  • @DevSolar I agree, but I have deleted my original comment because it was messed up by the introduction of comment markup on SO. – finnw Jul 14 '10 at 16:44
  • @DevSolar: That's how I do it. Nor do I ever have more than one pointer variable per definition (and darn few cases of any multiple variables per definition). – David Thornley Jul 14 '10 at 16:46
  • +1 for read from the right to left.. my professors never taught me that! –  Aug 11 '11 at 12:20
  • +1 for reading right-to-left `const int* i`, maybe the great left-to-right readability of trivial const value declarations should be mentioned, too. – Wolf Jun 18 '14 at 08:57
  • @DevSolar, The * should be glued to what will be what will be const: const int *i; int* const i; int* const* i; Just another visual clue to help. – ATL_DEV May 29 '21 at 05:28
13

There's a class of examples where putting the const on the right of the type also helps avoid confusion.

If you have a pointer type in a typedef, then it is not possible to change the constness of the to type:

typedef int * PINT;
const PINT pi;

pi still has the type int * const, and this is the same no matter where you write the const.

Richard Corden
  • 21,389
  • 8
  • 58
  • 85
  • 5
    I don't think that's so confusing. Your example is a const (int*), since the typedef acts as a grouping -- similar to (int*) const. In contrast, a pointer to const is a (const int)* or an (int const)* – rlbond Jun 12 '09 at 20:30
  • 5
    Its not confusing if you can look at PINT and say: "It's a typedef therefore the const doesn't apply to the pointed to member, because *I* know that's what the standard says about typedefs.". What if PINT was a macro? Then the rules are different and the CV specifier will apply to the to type. Within reason your code should be clear and as unambiguous as you can make it. – Richard Corden Jun 17 '09 at 07:40
  • Ahead of my time.....East Const! http://slashslash.info/2018/02/a-foolish-consistency/ https://www.reddit.com/r/cpp/comments/80k8hc/a_blog_rant_on_east_const/ – Richard Corden Apr 17 '18 at 16:36
11

I hope this explanation from B. Stroustrup's FAQ on Style & Techniques will give you a definite answer.

Bjarne Stroustrup's C++ Style and Technique FAQ


I personaly prefer:

int const* pi;
int* const pi;

Because const identifies the left token which is intended to be const.

And you definitely keep the same consistency when using smth like that:

int const* const pi;

Instead of writing inconsistently:

const int* const pi;

And what happens if you have a pointer to pointer and so on:

int const* const* const pi;

Instead of:

const int* const* const pi;
ovanes
  • 5,483
  • 2
  • 34
  • 60
8

I was at a conference where Bjarne Stroustrup was giving a presentation, and he used something like const int* i. Someone asked him why does he use this style and he responded (paraphrasing):

"people like to see const first when something is constant."

Nemanja Trifunovic
  • 24,346
  • 3
  • 50
  • 88
  • 8
    Sadly, he didn't apply that principle to the syntax of "const" in the general case, or we wouldn't be having this discussion. – T.E.D. Jun 12 '09 at 18:24
  • Stroustrup may not have had much to do with the syntax of "const", as C++ just took it over from C. It wasn't, as I remember, part of K&R C, but was introduced more or less with the 1990 standard. – David Thornley Jun 12 '09 at 20:09
  • 3
    @David C++ dates from 1983, and the predecessor "C with classes" from the late seventies I think. C++ had const first, it was added to C with C90 – Pieter Jun 12 '09 at 20:59
  • IIRC, C++ got const after C considered -- end eventually rejected -- "readonly". – Max Lybbert Jul 07 '09 at 17:57
  • 6
    Bjarne claims that he invented const: http://www.research.att.com/~bs/bs%5Ffaq2.html#constplacement. This article also mentions that Bjarne initially considered "readonly". – Brent Bradburn Nov 13 '09 at 01:45
7

People typically use const int* blah because it reads well as English. I wouldn't underestimate the usefulness of that.

I find that the int* const blah variation is rare enough that it's not typically useful to make the more common definition backwards. I am, in general, not a fan of anything that even slightly obscures code in the general case, though it might provide some nominal benefit in the exceptional case.

See also "if (1 == a)". Some people really enjoy writing code that doesn't read as English. I am not one of those people.

Really, though, the rules behind const are simple. Look to the left, then to the right. So simple that I wouldn't think it's worth much attention in a style guide.

Dan Olson
  • 22,849
  • 4
  • 42
  • 56
  • 2
    This issue actually came up in the argument. As an old Ada coder I find it kind of funny. If code not reading well in English is a problem for you, you have no business whatsoever using a C-syntax language. It wasn't designed for English-like readability, and trying to impose same on it is just going to drive you batty. – T.E.D. Jun 12 '09 at 18:13
  • 3
    As an old C++ coder, I believe that if the small inconsistency in using const on the left side in the common case is a problem for you, you have no business whatsoever using a C-syntax language. It wasn't designed for consistency and trying to impose some on it is just going to drive you batty. Seriously, you and your friend have already wasted more time arguing about it than would be saved by choosing either one of your suggested standardizations. Fire anyone that can't understand both syntaxes and be done with it. – Dan Olson Jun 13 '09 at 05:29
  • @T.E.D: I think that's a strawman argument. Just because "perfect" readability isn't possible, we can still strive to make it a bit more readable. In particular, why not make variable declarations look the same way as they're spoken, when we have the option? – jalf Aug 21 '09 at 10:30
  • "...named blah". I guess I could take that. Note that you had to use the first person present perfect tense to do it though. Far more awkward than "Blah is a constant integer". But fair is fair. Put that in the answer and I'll take back the downvote (SO won't let me change the vote unless the answer changes) – T.E.D. Sep 02 '09 at 20:29
  • Heh. According to Wikipedia what you used is actually the "present continuous", as opposed to my "present simple". I suppose you could make it imperitive by changing it to "Declare a...". – T.E.D. Sep 02 '09 at 20:48
  • Yeah, it doesn't matter: "constant integer pointer" reads better to me than "integer constant pointer", but constant can function as both adjective and noun, and integer is incorrectly used as an adjective in both cases (I think). It's a matter of preference, if I have to choose between readability and consistency I'm going to pick readability in this case because I think the loss of clarity due to readability is worse in this case. – Dan Olson Sep 03 '09 at 21:17
6

If it were only variables and pointers to them that could be const or not, it would probably not matter that much. But consider:

class MyClass
{
    public:
        int foo() const;
};

No way that const could be written anywhere else but trailing the function it refers to.

The shorter a style guide, the more likely developers will follow it. And the shortest rule possible, and the only rule that will give you consistency, is:

The const keyword always trails whatever it is referring to.

So, I'd say 0:3 for your coworker here.

Regarding your "ultimate issue": For the sake of the style guide, it does not matter whether the guide "discourages" or "bans" the things it speaks out against. That is a social issue, a policy. The style guide itself should be as crisp and short as possible. Long style guides just get ignored by everybody (except management on the lookout for someone to blame), so just write "do" or "don't", and state what you do with violations of the guide elsewhere (e.g. in the company policy of how peer reviews are being done).

DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • ...but the foo method isn't const itself. – Wolf Jun 18 '14 at 09:02
  • @Wolf: Yes it is, a [const member function](http://www.parashift.com/c++-faq/const-member-fns.html). – DevSolar Jun 18 '14 at 09:32
  • I know, that's its *name*, but the constness of a member function differs from that of data. – Wolf Jun 18 '14 at 09:53
  • @Wolf: But the point remains: You can place the `const` specifier to the *right* of what it's referring to anytime, but you can put it to the *left* only in a few special cases. – DevSolar Jun 18 '14 at 09:55
  • Absolutely, *and* the pattern `const ` seems nevertheless to be very common for data declarations. I use it so long, but now I really consider rethinking that. – Wolf Jun 18 '14 at 10:03
5

While there is no meaningful difference between const int and int const (and I've seen both styles in use), there is a difference between const int * and int * const.

In the first, you have a pointer to a const int. You can change the pointer, but you can't change the value it points to. In the second, you have a const pointer to int. You can't change the pointer (hope it's initialized to your liking), but you can change the value of the pointed-to int.

The proper comparison is with const int * and int const *, which both are pointers to a const int.

Remember that the * doesn't necessarily work as you might like. The declaration int x, y; will work as you expect, but int* x, y; declares one pointer to int, and one int.

David Thornley
  • 56,304
  • 9
  • 91
  • 158
4

Putting "const" after the type declaration makes a whole lot more sense once you train yourself to read your C++ type declarations from right to left.

I'm going to peg your cow-orker at 0-for-3 :)

Not Sure
  • 5,873
  • 3
  • 23
  • 29
  • ...but not if you read from left to right, which is the normal case, for instance `const int N = 26` can be read as *the constant integer N has the value 26*. – Wolf Jun 18 '14 at 09:06
  • @Wolf: And `int const N = 26` can be read as *the integer constant N has the value 26.* – DevSolar Jun 18 '14 at 09:39
  • @DevSolar, yes that's absolutely true (as I found out, sorry for my weak English). Thanks for clarifying again :) – Wolf Jun 18 '14 at 09:51
3

Let me put my 2¢ into the discussion.

In modern C++ I'd recommend to stick to int const instead of const int to highlight the difference between const and constexpr. It would help programmer to remember that const int cannot be always thought as compile-time constant, because:

  • compiler may (will?) allocate memory for it,
  • this memory may even be not write-protected (stack segment),
  • such a constant cannot serve all the duties constexpr can.
Community
  • 1
  • 1
firegurafiku
  • 3,017
  • 1
  • 28
  • 37
3

Personally I (and it is a personal preeference) I finding reading type declarations from right to left the easiest. Especially when you start throwing references into the mix.

std::string const&  name = plop; // reference to const string.

const std::string&  flame =plop; // reference to string const;
                                 // That works better if you are German I suppose :-)
Martin York
  • 257,169
  • 86
  • 333
  • 562
3

The ultimate issue here is that he thinks that putting const after int is so unspeakably ugly, and so harmful to readability that it should be banned in the style guide

Really?

Show me a programmer who gets bogged down when he sees:

int foo() {
}

vs

int foo()
{
}

...and I'll show you a programmer who doesn't pay close enough attention to detail.

No professional programmer worth his salt will have a problem with superficial differences in style.

EDIT: It is true that const int* and int* const don't mean exactly the same thing, but that wasn't the point. The point made by OP's coworker was that differences in style make code difficult to understand & maintain. It is this claim I disagree with.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • 3
    Show me a programmer who thinks those mean the same thing, and I'll show you a programmer who doesn't pay close enough attention to detail. – David Thornley Jun 12 '09 at 20:07
  • True they don't mean the same thing, but that wasn't the argument. The argument was that the difference in style is "so harmful to readability" that it should be outlawed. If you don't like the const int* vs int* const argument, fine. We could extend the conversation to be about curly braces. My claim is that no good programmer will have a problem understanding code because of a style difference. So don't sweat the small stuff. – John Dibling Jun 12 '09 at 20:15
  • 2
    Actually, the root of the difference is "const int*" vs. "int const *" – T.E.D. Jun 12 '09 at 20:53
2

I like to to use the following form for declaring "manifest constants". In this case, the value itself is a constant so I put the "const" first (same as Bjarne) to emphasize that the constness should be manifest at compile-time, and usable as such for specific optimizations by the compiler.

const int i = 123;

For declaring references which will not be used to modify the value, I use the following form which emphasizes the fact that the identifier is a "constant reference". The referenced value may or may not be a constant. [Related discussion: Would you even be using "const" for function parameters if they were not pointers or references? Use of 'const' for function parameters]

void fn( int const & i );

For pointers, I use the same form that I use for references, for essentially the same reason (although the term "constant pointer" seems a little more ambiguous than "constant reference").

void fn( int const * i );

Also, as another poster noted, this form remains consistent when you have multiple levels of indirection.

void fn( int const * const * i );

The final scenario, where you are declaring a pointer which is constant is pretty rare in my experience with C++. In any case, you don't really have any choices here. [This case demonstrates that the most consistent approach would be to put the word "const" after the type -- since that is, in fact, required for this particular declaration.]

void fn( int * const i );

...unless you use a typedef.

typedef int * IntPtr;

void fn1( const IntPtr i );
void fn2( IntPtr const i );

One final note: Unless you are working in a low-level domain, most C++ code should never declare a pointer. Therefore, that aspect of this discussion is probably more relevant to C.

Community
  • 1
  • 1
Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173
  • 1
    That's totally not true! There are plenty of uses for pointers. For example, a pointer to a choice of local variables. – rlbond Nov 13 '09 at 06:05
  • @rlbond: I'm not sure I understand your example, but I'm guessing that a reference would work for that. – Brent Bradburn Nov 13 '09 at 16:34
  • 1
    @rlbond: You're right that pointers have many uses. It's just that C++ gives you better (safer) ways to do what pointers did in C. C++ is a multi-paradigm language, and using the low-level (pointer-based) paradigm is important for some purposes, but in most cases, you're probably better off trying to minimize the use of raw pointers in favor of higher-level abstractions. – Brent Bradburn Nov 13 '09 at 16:35
  • [This question](http://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-int-const) addresses legality and interpretation. Included on that page is a very interesting comment which is worth repeating: "a rule of thumb which may help you remember how to discover whether 'const' applies to pointer or to pointed data: **split the statement at the asterisk**, then, if the const keyword appears in the *left part*, **it belongs to pointed data** -- if it's in the *right part*, **it's about the pointer**". This analysis also applies to `restrict` for C. – Brent Bradburn Apr 21 '13 at 21:31
2

I agree with both of you. You should put the const after the type. I also find looking at it an abomination that must be destroyed. But my recent foray into the wonders of const value parameters has made me understand why putting the const second makes sense.

int *
int const *
int * const
int const * const

Just looking at that has the hairs on my neck standing. I'm sure it would confuse my co-workers.

EDIT: I was just wondering about using this in classes:

class Foo {
    Bar* const bar;
    Foo(const Foo&) = delete; // would cause too many headaches
public:
    Foo() : bar(new Bar) {}
    ~Foo() { delete bar; }
};

bar in this example is functionally equivalent to Bar& but it is on the heap and can be deleted. For the lifetime of each Foo, there will be a single Bar associated with it.

Community
  • 1
  • 1
jmucchiello
  • 18,754
  • 7
  • 41
  • 61
2

Rules are good to follow. Simpler rules are better. Const goes to the right of what's const.

Take this declaration:

int main ( int const argc , char const * const * const argv ) ...

1

In modern C++11, you could also use template typedefs to add clarity to complicated declarations:

template<typename T>
using Const = const T;

template<typename T>
using Ptr = T*;

The three declarations you mentioned in your question:

int const * a;
int * const b;
int * const * c;

would then be written as:

Ptr<Const<int>> a;
Const<Ptr<int>> b;
Ptr<Const<Ptr<int>>> c;
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • Perhaps its because the feature is new, but I don't find that considerably easier to decipher. Suppose there's a bug somewhere. It looks like a lot of work to convince myself that the declarations on the last line are correct, compared to the three lines in the middle. – T.E.D. Oct 26 '12 at 17:55
  • I suppose. It still seems like I'd be much better off just sticking to the "const goes to the right" rule and not needing those extra declarations. – T.E.D. Oct 26 '12 at 19:04
  • I'm voting this answer up (because I think it's cool that this is possible, and I'm glad you mentioned it), even though the syntax makes my brain hurt and I would never use it. – Todd Lehman Aug 11 '14 at 02:00