views:

1519

answers:

16

So why exactly is it that it's always recommended to use const as often as possible? It seems to me that using const can be more of a pain than a help in C++. But then again, I'm coming at this from the python perspective: if you don't want something to be changed, don't change it. So with that said, here are a few questions:

  1. It seems like every time I mark something as const, I get an error and have to change some other function somewhere to be const too. Then this causes me to have to change another function somewhere else. Is this something that just gets easier with experience?

  2. Are benefits of using const really enough to compensate for the trouble? If you don't intend on changing an object, why not just not write code that changes it?

I should note that at this point in time, I'm most focused on the benefits of using const for correctness and maintainability purposes, although it is also nice to have an idea of the performance implications.

EDIT: I'm told that the correct term is const correctness, so that's what the title is now.

+46  A: 

Here's a piece of code with a common error that const correctness can protect you against:

void foo(const int DEFCON)
{
   if (DEFCON = 1)     //< FLAGGED AS COMPILER ERROR! WORLD SAVED!
   {
       fire_missiles();
   }
}
Doug T.
So we're saying that const is necessary because some bloody idiot chose "=" as the assignment operator in C? ;-)
Steve Jessop
Of course, most modern compilers warn about assignments in conditionals and we all turn on the treat warnings as errors flag, right :->
Jack Bolding
Of course, since foo gets it's own private copy of DEFCON to work with, the real DEFCON value would be unchanged anyway.
Eclipse
@Jost, true, but the world would still get nuked!
Doug T.
Don't be too hard on that example: This is the same example evangelized by some developers to convince us to use if(0 ==i) instead of if(i == 0). At last, Doug's pattern of code can be used outside the "if" statement. What's important is it shows one of the benefits of const in a humorous way. + 1.
paercebal
Some compilers (and lints) have been warning about this for a long time, and that is much more useful to catch this typo than const: http://codepad.org/Nnf5JUXV.
Roger Pate
@Roger you assume that we live in a world where builds are clean and warning free. My experience is that in a lot of code warnings get lost in the noise. Also, there is a lot of code that does assignments in the if expression and many will argue that it is a valid, "good" style.
Doug T.
@Doug: This is not about style, as I use this pattern myself: you can make it obvious with `if ((a = b))`, which also makes it more readable. I won't open the debate about compiler warnings here, but I will point out that various lint tools are more configurable (so no noise), don't require you to change your compiler, and a complete solution to the problem of ==/= typos, while using const only catches some of them.
Roger Pate
+2  A: 

There is a nice article here about const in c++. Its a pretty straight forward opinion but hope it helps some.

Ólafur Waage
+16  A: 

It's not for you when you are writing the code initially. It's for someone else (or you a few months later) who is looking at the method declaration inside the class or interface to see what it does. Not modifying an object is a significant piece of information to glean from that.

Antonio Haley
This is only kind of true. Const is used as protection as well to enforce in-variables through interfaces and so forth.
j0rd4n
It is, but you can enforce that through disciplined coding practices, and the poster states. The real benefit comes from the this being reflected in the API.
Antonio Haley
Exactly. It's better to have "const int Value = 5 ;" than have "int ConstValue = 5 ;". +1.
paercebal
The right time to put const-correctness in is when you write the API initially. Otherwise you'll get into trouble with const-poisoning when you retrofit it (which is why adding it to old code is a *completely different matter* to doing it in new code).
Donal Fellows
+45  A: 

This is the definitive article on "const correctness": http://www.parashift.com/c++-faq-lite/const-correctness.html.

In a nutshell, using const is good practice because it protects you from changing variables that really shouldn't be changed. You are correct in that it can be a pain in the rear to get them all, but the end code is more concise and safer to program with. When you do a lot of C++ development, the benefits of this quickly manifest.

At the same time, the compiler can generate more efficient code because it knows exactly what the state of the variable/function will be at all times. If you are writing tight C++ code, this is good.

As a fellow C++ developer, my opinion is to use it and use it correctly.

j0rd4n
+8  A: 

const helps you isolate code that "change things" behind your back. So, in a class, you'd mark all methods that don't change the state of the object as const. This means that const instances of that class will no longer be able to call any non-const methods. This way, you're prevented from accidentally calling functionality that can change your object.

Also, const is part of the overload mechanism, so you can have two methods with identical signatures, but one with const and one without. The one with const is called for const references, and the other one is called for non-const references.

Example:

#include <iostream>

class HelloWorld {
    bool hw_called;

public:
    HelloWorld() : hw_called(false) {}

    void hw() const {
        std::cout << "Hello, world! (const)\n";
        // hw_called = true;  <-- not allowed
    }

    void hw() {
        std::cout << "Hello, world! (non-const)\n";
        hw_called = true;
    }
};

int
main()
{
    HelloWorld hw;
    HelloWorld* phw1(&hw);
    HelloWorld const* phw2(&hw);

    hw.hw();    // calls non-const version
    phw1->hw(); // calls non-const version
    phw2->hw(); // calls const version
    return 0;
}
Chris Jester-Young
A: 

I like const correctness ... in theory. By every time I have tried to apply it rigourously in practice it has broken down eventually and const_cast starts to creep in making the code ugly.

Maybe it is just the design patterns I use, but const always ends up being too broad a brush.

For example, imagine a simple database engine ... it has schema objects, tables, fields etc. A user may have a 'const Table' pointer meaning that they are not allowed to modify the table schema itself ... but what about manipulating the data associated with the table? If the Insert() method is marked const then internally it has to cast the const-ness away to actually manipulate the database. If it isn't marked const then it doesn't protect against calling the AddField method.

Maybe the answer is to split the class up based on the const-ness requirements, but that tends to complicate the design more than I would like for the benefit it brings.

Rob Walker
I think your example is a case of overusing const, but don't forget about the mutable modifier, which can be applied to instance variables to remove the const-ness.
Zooba
When would an Insert() function ever be marked const unless its misnamed? Adding things usually modifies the thing you added it to, meaning it isn't const. What you really wanted was a TableWithConstSchema.
Greg Rogers
I could add another class, but I don't want to make the API unnecessarily complex purely for the sake of const-correctness.
Rob Walker
+2  A: 

When you use the "const" keyword, you're specifying another interface to your classes. There is an interface that includes all methods, and an interface that includes only the const methods. Obviously this lets you restrict access to some things that you don't want changed.

Yes, it does get easier with time.

Wesley Tarle
+17  A: 

It seems like every time I mark something as const, I get an error and have to change some other function somewhere to be const too. Then this causes me to have to change another function somewhere else. Is this something that just gets easier with experience?

From experience, this is a total myth. It happens when non const-correct sits with const-correct code, sure. If you design const-correct from the start, this should NEVER be an issue. If you make something const, and then something else doesn't complile, the compiler is telling you something extremely important, and you should take the time to fix it properly.

Chris Mayer
+9  A: 

My philosophy is that if you're going to use a nit-picky language with compile time checks than make the best use of it you can. const is a compiler enforced way of communicating what you mean... it's better than comments or doxygen will ever be. You're paying the price, why not derive the value?

Pat Notz
+9  A: 

const is a promise your are making as a developer, and enlisting the compiler's help in enforcing.

My reasons for being const-correct:

  • It communicates to clients of your function that your will not change the variable or object
  • Accepting arguments by const reference gives you the efficiency of passing by reference with the safety of passing by value.
  • Writing your interfaces as const correct will enable clients to use them. If you write your interface to take in non-const references, clients who are using const will need to cast constness away in order to work with you. This is especially annoying if your interface accepts non-const char*'s, and your clients are using std::strings, since you can only get a const char* from them.
  • Using const will enlist the compiler in keeping you honest so you don't mistakenly change something that shouldn't change.
JohnMcG
+4  A: 

For embedded programming, using const judiciously when declaring global data structures can save a lot of RAM by causing the constant data to be located in ROM or flash without copying to RAM at boot time.

In everyday programming, using const carefully helps you avoid writing programs that crash or behave unpredictably because they attempt to modify string literals and other constant global data.

When working with other programmers on large projects, using const properly helps prevent the other programmers from throttling you.

bk1e
+2  A: 

Say you have a variable in Python. You know you aren't supposed to modify it. What if you accidentally do?

C++ gives you a way to protect yourself from accidentally doing something you weren't supposed to be able to do in the first place. Technically you can get around it anyways, but you have to put in extra work to shoot yourself.

Greg Rogers
A: 

You can give the compiler hints with const as well....as per the following code

#include <string>

void f(const std::string& s)
{

}
void x( std::string& x)
{
}
void main()
{
    f("blah");
    x("blah");   // won't compile...
}
Keith Nicholas
+4  A: 

Programming C++ without const is like driving without the safety belt on.

It's a pain to put the safety belt on each time you step in the car, and 364 out of 365 days you'll arrive safely.

The only difference is that when you get in trouble with your car you'll feel it immediately, whereas with programming without const you may have to search for two weeks what caused that crash only to find out that you inadvertently messed up a function argument that you passed by non-const reference for efficiency.

andreas buykx
+8  A: 

If you use const rigorously, you'd be surprised how few real variables there are in most functions. Often no more than a loop counter. If your code is reaching that point, you get a warm feeling inside...validation by compilation...the realm of functional programming is nearby...you can almost touch it now...

QBziZ
+3  A: 

const correctness is one of those things that really needs to be in place from the beginning. As you've found, its a big pain to add it on later, especially when there is a lot of dependency between the new functions you are adding and old non-const-correct functions that already exist.

In a lot of the code that I write, its really been worth the effort because we tend to use composition a lot:

class A { ... }
class B { A m_a; const A& getA() const { return m_a; } };

If we did not have const-correctness, then you would have to resort to returning complex objects by value in order to assure yourself that nobody was manipulating class B's internal state behind your back.

In short, const-correctness is a defensive programming mechanism to save yourself from pain down the road.

Peter Kovacs