tags:

views:

3748

answers:

26

How far do you go with const? Do you just make functions const when necessary or do you go the whole hog and use it everywhere? For example, imagine a simple mutator that takes a single boolean parameter:

void SetValue(const bool b) { my_val_ = b; }

Is that const actually useful? Personally I opt to use it extensively, including parameters, but in this case I wonder if it's worthwhile?

I was also surprised to learn that you can omit const from parameters in a function declaration but can include it in the function definition, e.g.:

.h file

void func(int n, long l);

.cpp file

void func(const int n, const long l)

Is there a reason for this? It seems a little unusual to me.

+25  A: 

The reason is that const for the parameter only applies locally within the function, since it is working on a copy of the data. This means the function signature is really the same anyways. It's probably bad style to do this a lot though.

I personally tend to not use const except for reference and pointer parameters. For copied objects it doesn't really matter, although it can be safer as it signals intent within the function. Its really a judgement call. I do tend to use const_iterator though when looping on something when I don't intend on modifying it, so I guess to each his own, as long as const correctness for reference types is rigorously maintained.

Greg Rogers
I can't agree with the 'bad style' part. Dropping `const` from function prototypes has the advantage that you don't need to alter the header file if you decide to drop `const` from implementation part later.
Michał Górny
+1  A: 

I use const on function parameters that are references (or pointers) which are only [in] data and will not be modified by the function. Meaning, when the purpose of using a reference is to avoid copying data and not to allow changing the passed parameter.

Putting const on the boolean b parameter in your example only puts a constraint on the implementation and doesn't contribute for the class's interface (although not changing parameters is usually advised).

The function signature for

void foo(int a);

and

void foo(const int a);

is the same, which explains your .c and .h

Asaf

Asaf R
+1  A: 

In the case you mention, it doesn't affect callers of your API, which is why it's not commonly done (and isn't necessary in the header). It only affects the implementation of your function.

It's not particularly a bad thing to do, but the benefits aren't that great given that it doesn't affect your API, and it adds typing, so it's not usually done.

Luke Halliwell
A: 

I wouldn't put const on parameters like that - everyone already knows that a boolean (as opposed to a boolean&) is constant, so adding it in will make people think "wait, what?" or even that you're passing the parameter by reference.

Khoth
sometimes you'd want to pass an object by reference (for performance reasons) but not change it, so const is mandatory then. Keeping all such parameters - even bools - const would then be good practise, making your code easier to read.
gbjbaanb
A: 

the thing to remember with const is that it is much easier to make things const from the start, than it is to try and put them in later.

Use const when you want something to be unchanged - its an added hint that describes what your function does and what to expect. I've seen many an C API that could do with some of them, especially ones that accept c-strings!

I'd be more inclined to omit the const keyword in the cpp file than the header, but as I tend to cut+paste them, they'd be kept in both places. I have no idea why the compiler allows that, I guess its a compiler thing. Best practice is definitely to put your const keyword in both files.

gbjbaanb
+1  A: 

Ah, a tough one. On one side, a declaration is a contract and it really does not make sense to pass a const argument by value. On the other hand, if you look at the function implementation, you give the compiler more chances to optimize if you declare an argument constant.

Nemanja Trifunovic
A: 

All the consts in your examples have no purpose. C++ is pass-by-value by default, so the function gets copies of those ints and booleans. Even if the function does modify them, the caller's copy is not affected.

So I'd avoid extra consts because

  • They're redudant
  • They clutter up the text
  • They prevent me from changing the passed in value in cases where it might be useful or efficient.
AShelly
A: 

There's really no reason to make a value-parameter "const" as the function can only modify a copy of the variable anyway.

The reason to use "const" is if you're passing something bigger (e.g. a struct with lots of members) by reference, in which case it ensures that the function can't modify it; or rather, the compiler will complain if you try to modify it in the conventional way. It prevents it from being accidentally modified.

MarkR
A: 

I use const were I can. const for parameters means that they should not change thier value. This especially valueble when passing by reference. const for funcion declairs that the function should not change the classes members.

Dror Helper
+1  A: 

I do not use const for value-passed parametere. The caller does not care whether you modify the parameter or not, it's an implementation detail.

What is really important is to mark methods as const if they do not modify their instance. Do this as you go, because otherwise you might end up with either lots of const_cast<> or you might find that marking a method const requires changing a lot of code because it calls other methods which should have been marked const.

I also tend to mark local vars const if I do not need to modify them. I believe it makes the code easier to understand by making it easier to identify the "moving parts".

agateau
+1  A: 

Const parameter is useful only when the parameter is passed by reference i.e., either reference or pointer. When compiler sees a const parameter, it make sure that the variable used in the parameter is not modified within the body of the function. Why would anyone want to make a by-value parameter as constant? :-)

A: 

If the parameter is passed by value (and is not a reference), usually there is not much difference whether the parameter is declared as const or not (unless it contains a reference member -- not a problem for built-in types). If the parameter is a reference or pointer, it is usually better to protect the referenced/pointed-to memory, not the pointer itself (I think you cannot make the reference itself const, not that it matters much as you cannot change the referee). It seems a good idea to protect everything you can as const. You can omit it without fear of making a mistake if the parameters are just PODs (including built-in types) and there is no chance of them changing further along the road (e.g. in your example the bool parameter).

I didn't know about the .h/.cpp file declaration difference, but it does make some sense. At the machine code level, nothing is "const", so if you declare a function (in the .h) as non-const, the code is the same as if you declare it as const (optimizations aside). However, it helps you to enlist the compiler that you will not change the value of the variable inside the implementation of the function (.ccp). It might come handy in the case when you're inheriting from an interface that allows change, but you don't need to change to parameter to achieve the required functionality.

Attila
+1  A: 

I tend to use const wherever possible. (Or other appropriate keyword for the target language.) I do this purely because it allows the compiler to make extra optimizations that it would not be able to make otherwise. Since I have no idea what these optimizations may be, I always do it, even where it seems silly.

For all I know, the compiler might very well see a const value parameter, and say, "Hey, this function isn't modifying it anyway, so I can pass by reference and save some clock cycles." I don't think it ever would do such a thing, since it changes the function signature, but it makes the point. Maybe it does some different stack manipulation or something... The point is, I don't know, but I do know trying to be smarter than the compiler only leads to me being shamed.

C++ has some extra baggage, with the idea of const-correctness, so it becomes even more important.

jdmichal
+5  A: 

The following two lines are functionally equivalent:

int foo (int a);
int foo (const int a);

Obviously you won't be able to modify a in the body of foo if it's defined the second way, but there's no difference from the outside.

Where const really comes in handy is with reference or pointer parameters:

int foo (const BigStruct &a);
int foo (const BigStruct *a);

What this says is that foo can take a large parameter, perhaps a data structure that's gigabytes in size, without copying it. Also, it says to the caller, "Foo won't* change the contents of that parameter." Passing a const reference also allows the compiler to make certain performance decisions.

*: Unless it casts away the const-ness, but that's another post.

Ben Straub
+1  A: 

const is pointless when the argument is passed by value since you will not be modifying the caller's object.

const should be preferred when passing by reference, unless the purpose of the function is to modify the passed value.

Finally, a function which does not modify current object (this) can, and probably should be declared const. An example is below:

int SomeClass::GetValue() const {return m_internalValue;}

This is a promise to not modify the object to which this call is applied. In other words, you can call:

const SomeClass* pSomeClass;
pSomeClass->GetValue();

If the function was not const, this would result in a compiler warning.

Dan Hewett
+40  A: 

"const is pointless when the argument is passed by value since you will not be modifying the caller's object."

Wrong.

It's about self-documenting your code and your assumptions.

If your code has many people working on it and your functions are non-trivial then you should mark "const" any and everything that you can. When writing industrial-strength code, you should always assume that your coworkers are psychopaths trying to get you any way they can (especially since it's often yourself in the future).

Besides, as somebody mentioned earlier, it might help the compiler optimize things a bit (though it's a long shot).

rlerallut
Totally agree. It's all about communicating with people and restricting what could be done with a variable to what should be done.
Len Holgate
I've voted this one down. I think you dilute what you're trying to indicate with const when you apply it to simple pass by value arguments.
tonylo
I've voted this one up. Declaring the parameter 'const' adds semantic information to the parameter. They highlight what the original author of the code had intended and this will aid maintenance of the code as time goes by.
Richard Corden
@tonylo: you misunderstand. This is about marking a local variable as const inside a block of code (that happens to be a function). I would do the same for any local variable. It is orthogonal to having an API that is const-correct, which is indeed also important.
rlerallut
Not really, I think you're just overestimating the usefulness of const. I think [the usefulness] it kicks in when the ownership of a object is important to define. Take a look at POSIX APIs, open(2) for e.g. the pathname (pointer) is worthwhile making const, for the flags and modes it's irrelevant.
tonylo
And it can catch bugs *inside* the function -- if you know that a parameter shouldn't be changed, then declaring it const means that the compiler will tell you if you accidently modify it.
Adrian
@tonylo, i'm being rather neutral to this issue. If people put const in parameters, good. But i don't do it in my code. But mentioning manpages `open` and so on isn't really an argument. Because the `const` wouldn't be part of the interface. So it would be wrong to show the `const` in manpages.
Johannes Schaub - litb
@litb: It is never wrong to write a const when you need it!
Partial
@litb: Have a look at this article: http://www.linuxjournal.com/article/7629
Partial
@Partial, i do not disagree with you in that it's never wrong to write it. But it's also not wrong to not always stick it everywhere. There are cases where i find the benefit doesn't justify it. This is a personal opinion: You will never see me downvoting any such answer just because of my personal opinion, and you will never read me writing that putting const anywhere is wrong.
Johannes Schaub - litb
But it limits your choice of algorithms (or forces you to make unnecessary copies) - if I call your sin(x) I don't care if your sin() algorithm should change it's copy of X while it's evaluating the answer.
Martin Beckett
+1  A: 

Sometimes (too often!) I have to untangle someone else's C++ code. And we all know that someone else's C++ code is a complete mess almost by definition :) So the first thing I do to decipher local data flow is put const in every variable definition until compiler starts barking. This means const-qualifying value arguments as well, because they are just fancy local variables initialized by caller.

Ah, I wish variables where const by default and mutable was required for non-const variables :)

Constantin
+1: Great answer
Partial
+14  A: 

When I coded C++ for a living I consted everything I possibly could. Using const is a great way to help the compiler help you. For instance, const-ing your method return values can save you from typos such as:

foo() = 42

when you meant:

foo() == 42

If foo() is defined without a const:

int foo() { /* ... */ }

The compiler will happily let you assign a value to the anonymous temporary returned by the function call. Making it const:

const int foo() { /* ... */ }

Eliminates this possibility.

Avdi
With what compiler did that work?GCC gives an error while trying to compile `foo() = 42`: error: lvalue required as left operand of assignment
gavrie
+1  A: 

Marking value parameters 'const' is definitely a subjective thing.

However I actually prefer to mark value parameters const, just like in your example.

void func(const int n, const long l) { /* ... */ }

The value to me is in clearly indicating that the function parameter values are never changed by the function. They will have the same value at the beginning as at the end. For me, it is part of keeping to a very functional programming sort of style.

For a short function, it's arguably a waste of time/space to have the 'const' there, since it's usually pretty obvious that the arguments aren't modified by the function.

However for a larger function, its a form of implementation documentation, and it is enforced by the compiler.

I can be sure if I make some computation with 'n' and 'l', I can refactor/move that computation without fear of getting a different result because I missed a place where one or both is changed.

Since it is an implementation detail, you don't need to declare the value parameters const in the header, just like you don't need to declare the function parameters with the same names as the implementation uses.

Lloyd
+4  A: 

@letseatlunch

All you're doing by using any types is "limiting your programs". So what? I have no problem with "limiting my programs". Much more useful is "limiting my errors", and that's what const helps me do.

DrPizza
A: 

As parameters are being passed by value,it doesnt make any difference if you specify const or not from the calling function's perspective.It basically does not make any sense to declare pass by value parameters as const.

+2  A: 

const should have been the default in C++. Like this :

int i = 5 ; // i is a constant

var int i = 5 ; // i is a real variable
QBziZ
Exactly my thoughts.
Constantin
Compatibility with C is too important, at least for the people that design C++, to even consider this.
Roger Pate
A: 

I say const your value parameters.

Consider this buggy function:

bool isZero(int number)
{
  if (number = 0)  // whoops, should be number == 0
    return true;
  else
    return false;
}

If the number parameter was const, the compiler would stop and warn us of the bug.

another way is using if(0 == number) ... else ...;
Johannes Schaub - litb
that's just horrible though!
Chris Huang-Leaver
+2  A: 

There is a good discussion on this topic in the old "Guru of the Week" articles on comp.lang.c++.moderated here.

The corresponding GOTW article is available on Herb Sutter's web site here.

Void
A: 

On compiler optimizations: http://www.gotw.ca/gotw/081.htm

sdcvvc
A: 

This video should answer your question :)

Victor T.