• 0

[C++] Coding style of const local variables


Question

I've been wondering about this recently (and haven't been able to find any good resources online).

Would you make local variables that should not (or do not) change const?

From following several other projects they always seem to leave them non-const.

But I thought it is a fairly good documentation tool to make them const, although it does clutter up the code somewhat, especially if you have something like "int const * p;".

This is more of a style question, so I don't care if there are or are not any performance improvements.

22 answers to this question

Recommended Posts

  • 0

As far as an online resource: stackoverflow.com. All the gurus and professional developers answer questions there. I wouldn't be where I was if it wasn't for them. I've done very little C++ but that's because I'm caught up with PHP at this point in time...

I would like to try to answer your question but I recommend you visit the link instead if you'd like to get a thorough answer.

  • 0
  On 09/04/2011 at 13:56, Lant said:

Would you make local variables that should not (or do not) change const?

If a value does not change, then I usually declare it as a static const or a preprocessor symbol. If the variable should not change because of program logic, for instance, passing a variable to a function that doesn't have permission to change it, then a simple constant qualifier is sufficient.

  On 09/04/2011 at 13:56, Lant said:

From following several other projects they always seem to leave them non-const.

But I thought it is a fairly good documentation tool to make them const, although it does clutter up the code somewhat, especially if you have something like "int const * p;".

It certainly makes code more readable, manageable, and helps to isolate logic and behavioural errors.

  On 09/04/2011 at 13:56, Lant said:

This is more of a style question, so I don't care if there are or are not any performance improvements.

It's not merely a question of style. because a constant qualifier determines how a variable can be used. It's also self documenting, prevents unexpected behaviour, and allows the compiler to perform additional optimisations.

  • 0
  On 09/04/2011 at 13:59, surrealvortex said:

No point really. I would rather include a clear comment indicating that the value should not change.

Yes, but why include a comment when it can be ignored later on when you can add a const that will be enforced by the compiler?

  • 0
  On 09/04/2011 at 14:12, Flawed said:

If a value does not change, then I usually declare it as a static const or a preprocessor symbol. If the variable should not change because of program logic, for instance, passing a variable to a function that doesn't have permission to change it, then a simple constant qualifier is sufficient.

I'm talking about local variables inside functions here, not class level or global constants.

Plenty of my code is like the following:


bool x(C c)
{
std::vector<int> v = c.fn();
int i = c.fn2();


if ( std::find(v.begin(), v.end(), i) != v.end() )
...

return ;
}
[/CODE]

If v and i was never going to be modified by the rest of the function should I make them const?

Edited by Lant
  • 0
  On 09/04/2011 at 13:59, surrealvortex said:

No point really. I would rather include a clear comment indicating that the value should not change.

And permit behaviour that defies the design of the program? You're inviting problems if you follow that path. Let the code document itself, and at the same time prevent unexpected behaviour; it's far easier to debug and certify your application this way.

  • 0
  On 09/04/2011 at 14:19, Lant said:

I'm talking about local variables inside functions here, not class level or global constants.

Plenty of my code is like the following:


bool x(C c)
{
std::vector<int> v = c.fn();
int i = c.fn2();


if ( std::find(v.begin(), v.end(), i) != v.end() )
...

return ;
}
[/CODE]

If v and i was never going to be modified by the rest of the function should I make them const?

For instance in boost\date_time\src\gregorian\greg_month.cpp

[CODE]
special_values special_value_from_string(const std::string& s) {
short i = date_time::find_match(special_value_names,
special_value_names,
date_time::NumSpecialValues,
s);
if(i >= date_time::NumSpecialValues) { // match not found
return not_special;
}
else {
return static_cast<special_values>(i);
}
}
[/CODE]

The i is never changed, but it is not declared const.

This is from boost sources, and they use fairly up-to-date coding methods and styles.

So why don't they do it?

[b]I don't think in that example i is a constant. Simple as that.[/b]

Imagine if they call date_time::find_match() again within the program. If the i variable was a constant and date_time::find_match() returned a different value, the i variable would change and the program would throw a runtime error

Also, from: Stackoverflow.com

  Quote

In general, I think it's always a good idea to make your intentions clear this way, for a number of reasons:

It's easier to understand what you meant when you wrote it.

It's easier for others to reason about your code when they read it.

It's easier for the compiler to make inferences about what you want to do.

It's easier for the compiler to prevent logical errors.

Making variables constant is a perfectly legitimate way to accomplish all of the above, in the specific case of intending "I don't want this variable to change its value".

(This is why I love stack overflow, they just find the right words to explain which I'm bad at) :)

In short, it is strongly suggested you make the int a constant if the integer will not change throughout the program.

  • 0
  On 09/04/2011 at 14:19, Lant said:

I'm talking about local variables inside functions here, not class level or global constants.

Plenty of my code is like the following:


bool x(C c)
{
std::vector<int> v = c.fn();
int i = c.fn2();


if ( std::find(v.begin(), v.end(), i) != v.end() )
...

return ;
}
[/CODE]

If v and i was never going to be modified by the rest of the function should I make them const?

Why not write it as:

[CODE]
bool x(C c)
{
std::vector<int> v = c.fn();
if ( std::find(v.begin(), v.end(), c.fn2()) != v.end() )
...

return ;
}
[/CODE]

But if you insist on doing it that way, no I don't see a need to define it as a constant in the function. The const qualifier is most beneficial when two modules are interacting, or to prevent some unexpected behaviour. Use of it in a local function as in your example is unnecessary. There are cases though where you might want to define a static local constant for a function; for instance, in order to encapsulate/hide the details of it if it's specific to that function, or perhaps if a function returns a constant pointer, but for simple temporary values on the stack, there isn't much point.

  • 0
  On 09/04/2011 at 14:34, Flawed said:

Why not write it as:


bool x(C c)
{
std::vector<int> v = c.fn();
if ( std::find(v.begin(), v.end(), c.fn2()) != v.end() )
...

return ;
}
[/CODE]

But if you insist on doing it that way, no I don't see a need to define it as a constant in the function. The const qualifier is most beneficial when two modules are interacting, or to prevent some unexpected behaviour. Use of it in a local function as in your example is unnecessary. There are cases though where you might want to define a static local constant for a function; for instance, in order to encapsulate/hide the details of it if it's specific to that function, or perhaps if a function returns a constant pointer, but for simple temporary values on the stack, there isn't much point.

I disagree with this. For the same reasons I had posted in my reply above Flawed's post.

  • 0
  On 09/04/2011 at 14:25, Tekkerson said:

I don't think in that example i is a constant. Simple as that.

Imagine if they call date_time::find_match() again within the program. If the i variable was a constant and date_time::find_match() returned a different value, the i variable would change and the program would throw a runtime error

It could be declared "const short i" and it would all be perfectly fine until the static_cast which would probably cause a compile error as the cast is trying to remove constness. (I realised it was a bad example so I removed it)

But it wouldn't throw a runtime error.

  • 0
  On 09/04/2011 at 14:25, Tekkerson said:

In short, it is strongly suggested you make the int a constant if the integer will not change throughout the program.

I agree with "throughout the program", or even:

void my_func() {
static const int my_func_number = 12345;
/* do some work */
}

But for temporary local function variables, I don't really see a justification in general, and certainly not in the example code provided by the OP.

  • 0
  On 09/04/2011 at 14:44, Lant said:

It could be declared "const short i" and it would all be perfectly fine until the static_cast which would probably cause a compile error as the cast is trying to remove constness. (I realised it was a bad example so I removed it)

But it wouldn't throw a runtime error.

You know, that's funny at first I typed compile then I edited it to runtime... (thought processes got mixed up or something)

  • 0
  On 09/04/2011 at 14:45, Flawed said:

I agree with "throughout the program", or even:

void my_func() {
static const int my_func_number = 12345;
/* do some work */
}

But for temporary local function variables, I don't really see a justification in general, and certainly not in the example code provided by the OP.

If it's a constant, it should always be declared constant no matter where it is. What if for some reason you changed something in the code that made the variable change when it wasn't supposed to? It's just a good coding practice. But that's for the OP to decide.

  • 0
  On 09/04/2011 at 14:41, Tekkerson said:

I disagree with this. For the same reasons I had posted in my reply above Flawed's post.

That was talking in general, and I do agree with those principles as can be seen by my original post, but in general, temporary local function variables aren't likely to be const targets.

Edit: Removed my unnecessary sarcasm.

  • 0

My code is already littered with BOOST_STATIC_CONSTANTs,

what I was really after is if the documentation value of declaring local variables (mostly stl containers) const is worth it over the readability loss of adding const.

I suppose its just one of those things in C++ that there is no real answer either way

  • 0
  On 09/04/2011 at 14:53, Tekkerson said:

If it's a constant, it should always be declared constant no matter where it is. What if for some reason you changed something in the code that made the variable change when it wasn't supposed to? It's just a good coding practice. But that's for the OP to decide.

I agree in general with your logic, but you have to ask the question, why is that variable a constant? We are speculating without knowing the actual case. At first glance, I wouldn't declare it as a constant, but that's just me. Perhaps you are right.

  • 0
  On 09/04/2011 at 14:57, Flawed said:

That was talking in general, and I do agree with those principles as can be seen by my original post, but in general, temporary local function variables aren't likely to be const targets.

I do have another thing to add though. Even with Flawed's point, even in the smallest cases I just think it's a good habit to do it where it applies, Lant.

Though, in the end I think this is more of a personal question. It boils down to:

Would you prefer cleanliness/convenience (less declarations) over "correctness" (which also has it's benefits)? Which is what I think sums up both me and Flawed's point.

Edit: To fit with Flawed's edits. :p

  • 0
  On 09/04/2011 at 14:58, Lant said:

My code is already littered with BOOST_STATIC_CONSTANTs,

what I was really after is if the documentation value of declaring local variables (mostly stl containers) const is worth it over the readability loss of adding const.

I suppose its just one of those things in C++ that there is no real answer either way

It's the same in C as well. While I agree with most of what Tekkerson's said, in practise, I rarely use const qualifiers in my own code in temporary local function variables. The occasions when I do are, if I want to declare a static const value to be used only for that function only, or if another function returns a pointer value that is immutable.

Though now I think about it, Tekkerson's arguments are compelling. So if you find it makes your code more readable, manageable, and prevents program logic / behavioural errors, then go for it.

  • 0

I only use const where the language forces me to, for example:

void myFunction(const std::string&amp; arg); // const must be used to allow the following usage:
myFunction("String literal");

Having successfully developed applications in Python, where there is no equivalent of the C++ const keyword, I don't believe const adds enough value to be worth having to constantly (no pun intended) worry about it. I just put constants in ALL_CAPS and I never declare const methods.

  • 0
  On 09/04/2011 at 14:22, Flawed said:

And permit behaviour that defies the design of the program? You're inviting problems if you follow that path. Let the code document itself, and at the same time prevent unexpected behaviour; it's far easier to debug and certify your application this way.

Const variables can be modified indirectly. It is not foolproof.

I can see where you are coming from. The code definitely will document itself that way, but when I suggested adding a comment, I meant a detailed comment explaining the intention. Not something like: /*This is a const*/

  • 0
  On 09/04/2011 at 18:17, surrealvortex said:

Const variables can be modified indirectly. It is not foolproof.

I can see where you are coming from. The code definitely will document itself that way, but when I suggested adding a comment, I meant a detailed comment explaining the intention. Not something like: /*This is a const*/

I would discard what I said there. I misunderstood the original question, and that comment was aimed at function parameters and class/global scope variables. Nevertheless, I agree with what you are saying. A terse comment can help explain the variable's purpose and/or why it's immutable if it's not already self explanatory. Personally, I haven't really felt the need to use constant qualifiers at the function scope level except in the special circumstances I outlined previously, but I suppose as long as the code is readily readable, then either way would work.

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • AMD thinks Ryzen Threadripper 9000 wipes the floor with Intel by Sayan Sen At Computex 2025 earlier this year, AMD revealed its new Zen 5-based Ryzen Threadripper 9000 series with up to 96 cores, comprising the PRO 9000WX series and 9000 series chips. At the time though the company did not share performance numbers but given the specs, we had a fairly good idea of their capability. For those who may not be familiar with Ryzen Threadripper, it is AMD's desktop CPU lineup meant for workstations and HEDT (high-end desktop) builds and is placed between the mainstream Ryzen and the server EPYC lineups. With the launch expected to happen next month, performance numbers for the Ryzen Threadripper 9000 are now out. Before diving into the performance details, AMD has also shared a recap of some of the platform details and the compatible sTR5 socket. These new premium chips support up to 8 channels of DDR5-6400 memory and up to 128 PCIe 5.0 lanes for I/O. AMD also promises over 7000 MT/s of DDR5 support with EXPO. The specs of the Ryzen Threadripper 9000 lineup are given below: Processor SKU Cores Threads Base Clock (GHz) Boost Clock (GHz) L3 Cache (MB) Memory Channels PCIe Lanes TDP (W) AMD Ryzen Threadripper PRO 9995WX 96 192 2.5 5.45 384 8‑channel DDR5‑6400 ECC 128 PCIe Gen5 350 AMD Ryzen Threadripper PRO 9985WX 64 128 3.2 5.4 384 8‑channel DDR5‑6400 ECC 128 PCIe Gen5 350 AMD Ryzen Threadripper PRO 9975WX 32 64 3.2 5.4 384 8‑channel DDR5‑6400 ECC 128 PCIe Gen5 350 AMD Ryzen Threadripper PRO 9965WX 24 48 3.2 5.4 384 8‑channel DDR5‑6400 ECC 128 PCIe Gen5 350 AMD Ryzen Threadripper PRO 9955WX 16 32 3.2 5.4 384 8‑channel DDR5‑6400 ECC 128 PCIe Gen5 350 AMD Ryzen Threadripper PRO 9945WX 12 24 3.2 5.4 384 8‑channel DDR5‑6400 ECC 128 PCIe Gen5 350 AMD Ryzen Threadripper 9980X 64 128 3.2 5.4 256 4‑channel DDR5‑6400 92 PCIe Gen5 350 AMD Ryzen Threadripper 9970X 32 64 3.2 5.4 256 4‑channel DDR5‑6400 92 PCIe Gen5 350 AMD Ryzen Threadripper 9960X 24 48 3.2 5.4 256 4‑channel DDR5‑6400 92 PCIe Gen5 350 AMD has compared the 96-core 9995WX against the previous-gen 7995WX (images below), also with the same core configuration, and the 64-core 9980X, against Intel's 60-core Xeon W9-3595X. While Xeon has generally been associated with Server CPUs, the Xeon W chips are designed to be used in workstations. AMD follows a similar naming, too, wherein the W in the WX is meant to indicate workstation, and the non-W Threadripper is for HEDT. AMD claims up to 26% faster throughput on the newer 96-core 9995WX compared to the 7995WX. Meanwhile, against the Intel Xeon w9-3595X, AMD expects utter dominance from its 9980X with up to 108% faster performance. Even the lowest gain, says the company, is 22% over the Intel chip, and that is still very significant. AMD also compared the AI performance of the 9995WX vs the Xeon w9-3595X. The company promises up to 49% faster LLM processing, but keep in mind that the figures given include a GPU as well. Besides AI, performance related to other creative and professional workloads was also shared. In Keyshot rendering, for example, AMD claims up to 119% gains over the Xeon SKU. And in Chaos V-Ray, the 9995WX is said to offer nearly 2.5 times the performance. AMD has not released pricing information for the Threadripper 9000 series.
    • Funk Microsoft - I would switch from PS5 as you have better deals but the Xbox interface (I tried One S and later on, even one X i hate the interface and considering all MS changes in Windows interface over the years.. I hope they have a good one coming ps5 has also weird interface I had to get used too. But considering the library of ps4 games I wanted to be playable for me… I got used and adapted
    • I loved Sonic CD so much. I think I must have almost worn out that disc!
    • For what it's worth, if the game was scheduled for a September release, then most if not all of art assets, etc. were complete. That's the really expensive part of any AAA game. So going back into the code, game play, combat loop, etc. should be much easier and faster than re-imagining the look of the game entirely. That took years and zillions to create.
  • Recent Achievements

    • First Post
      Ian_ earned a badge
      First Post
    • Explorer
      JaviAl went up a rank
      Explorer
    • Reacting Well
      Cole Multipass earned a badge
      Reacting Well
    • Reacting Well
      JLP earned a badge
      Reacting Well
    • Week One Done
      Rhydderch earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      653
    2. 2
      ATLien_0
      267
    3. 3
      Michael Scrip
      218
    4. 4
      +FloatingFatMan
      188
    5. 5
      Steven P.
      146
  • Tell a friend

    Love Neowin? Tell a friend!