To bother or not to bother... "const" as function argument

Started by
31 comments, last by mgarriss 18 years, 10 months ago
Let's say you have a very simple function like this:
//would you write it like this...
void f(SSomeStruct& obj)
{
    std::cout << obj.x << std::endl;
}

//or like this:
void f(const SSomeStruct& obj)
{
    std::cout << obj.x << std::endl;
}

I know the latter example is more correct by definition, yet I never tend to use consts for function arguments. Why? Because they're just one more thing to think of. If I pass something by reference, I may suddenly realize I need to modify it, and then I must go back to the prototype. Either that, or typing "const " involves pressing 6 extra buttons on the keyboard for no immediate gain. Multiply this by the number of function arguments that should be constant in your program and you get into huge numbers quite quickly (then again, so is programming all other code already). I've seen professional code that ignores consts completely. I've seen posters at GameDev advoating why you shouldn't ignore them. Discuss!
Advertisement
Since you passed the parameter by value, it's more or less pointless. It only really matter when you pass by reference, at which point you should make everything that can be const, const.

Typing 6 extra characters is nothing compared to having the compiler ensure the object really won't be (accidentally) modified.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by Fruny
Since you passed the parameter by value, it's more or less pointless. It only really matter when you pass by reference, at which point you should make everything that can be const, const.

Typing 6 extra characters is nothing compared to having the compiler ensure the object really won't be (accidentally) modified.


Err you're right about that, I'll edit my example to accomodate for a better discussion...
Quote:I know the latter example is more correct by definition


Why? There's nothing more correct about that.

You might want to pass a smart pointer (NOT std::auto_ptr) or other ptr wrapper class by const value, but there's no reason you wouldn't pass that by const reference if you didn't want it altering.

Remember, const really exists for human benefit, no the compiler. It's a human guarentee that the funciton your calling won't logically alter your object.

There are plenty of good reason why a programmer might want to modify a value passed in a const (lazy evaluation for one).
Quote:Original post by Nitage
Quote:I know the latter example is more correct by definition


Why? There's nothing more correct about that.

You might want to pass a smart pointer (NOT std::auto_ptr) or other ptr wrapper class by const value, but there's no reason you wouldn't pass that by const reference if you didn't want it altering.


Well yeah, but the question is when in fact it seems redundant. I.e, I've heard people argue in these forums before that consts should always be applied for objects that are not modified, regardless of how likely that is to happen. I guess it's a bit of a cooperative thing; in a team I guess preventing other to misuse code is a higher priority than in a one man project.
Regarding your "no immediate gain" mention, const really shines when you make sure you use it properly in the whole program. If you just have a few const here and there, it will cause headaches - the "easy way out" being to remove the consts, which is a mistake: instead you should add more consts where they are needed. In the process of adding those const, either everything will fall into place, or you will find that you have a function that actually tried to modify the const entity. Which means that either the entity shouldn't have been const in the first place, or you've just found a nasty source of bugs.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by Unwise owl I guess it's a bit of a cooperative thing; in a team I guess preventing other to misuse code is a higher priority than in a one man project.


Passing by const value doesn't provide any guards against misuse unless you're passing a class/struct which contains a non-const pointer/reference or static variable.
Quote:Original post by Nitage
Quote:I know the latter example is more correct by definition


Why? There's nothing more correct about that.


The first function wouldn't be able to handle a const, literal, or unnamed temporary parameter. You're pointlessly restricting the kind of data it can deal with.

Quote:Remember, const really exists for human benefit, no the compiler. It's a human guarentee that the funciton your calling won't logically alter your object.


I had a C inline function that took a parameter by value and manipulated it in ASM. GCC optimized the variable copying away when I declared that parameter to be const. No, in that case, I couldn't have passed it by reference. That function was performance-critical - we gained an extra 10% by just adding that keyword.

So, yes, in most cases, const is for humans, but it may also help the compiler optimize the code - it knows you're not going to change the contents of the 'constant variable' within the function.

Quote:Original post by Nitage
Passing by const value doesn't provide any guards against misuse unless you're passing a class/struct which contains a non-const pointer/reference or static variable.


If a constant structure contains a pointer, then the pointer itself is constant, not the data it points to. What you say is true for a reference member, though. And a static variable is completely unaffected by the qualifications of any given instance. Passing by const value only means you won't be able to modify that value within the function. The original object it was copied from is unaffected in any case, const or no const.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:
Quote:Quote:Original post by Nitage
Passing by const value doesn't provide any guards against misuse unless you're passing a class/struct which contains a non-const pointer/reference or static variable.




If a constant structure contains a pointer, then the pointer itself is constant, not the data it points to. What you say is true for a reference member, though. And a static variable is completely unaffected by the qualifications of any given instance. Passing by const value only means you won't be able to modify that value within the function. The original object it was copied from is unaffected in any case, const or no const.


Consider:
class ptrWrapper(){   public:     int* get()const{return intPtr);   private:     int* intPtr;};void foo1(const ptrWrapper);void foo2(const ptrWrapper&);void foo3(ptrWrapper);


If const_cast isn't uses, foo1 and foo2 provide a guarentee the the original object passed in remains the same. foo3 doesn't. The original object may technically remain the same (the value of intPtr won't change, but the value of *intPtr will), but ny passing by value you probably intended for the value of *intPtr to remain the same.

My mistake with the static thing.
we use them for the same sort of reason we use public/private labels.

This topic is closed to new replies.

Advertisement