Sign in to follow this  

Semantically, should "setters" in C++ use constant parameters, even for built-ins?

This topic is 3199 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

void setX (const int x)
{
   _x = x;
}
To whomever is calling this function, the fact that x is const doesn't change a thing (though if x weren't a simple non-reference int, that would be a different story). However, x is not going to be changed in the function, so semantically, it seems it should be const. What do you think?

Share this post


Link to post
Share on other sites
Yeah, that's how I would write it (note: I never did until we started using Lint).

The compiler will still generate the same code, though. So it's only for your own convenience/annoyance (depending on the circumstances... there were many times I had to remove const on such parameter, because I was intentionally fiddling with it within a function)

Share this post


Link to post
Share on other sites
When talking about integral types or even iterator types then it is just a matter of personal preference which does not gain you anything. Personally I would always add constant and even the reference modifiers here, it is more times than not instinct rather than a process of thought, a coding habit you could say. Having said this, if I were to write a function like your example I would have to question (I realise it is for example purposes) why I was even writing it, why not just make it publicly assessable.

Share this post


Link to post
Share on other sites
Quote:
Original post by iaminternets

void setX (const int x)
{
_x = x;
}

To whomever is calling this function, the fact that x is const doesn't change a thing (though if x weren't a simple non-reference int, that would be a different story). However, x is not going to be changed in the function, so semantically, it seems it should be const. What do you think?
You're passing by const-value. This is pointless as you're getting a copy of x and then promising to not modify the copy.

Setters should either pass by const-reference or pass by value:
void setX (const int& x)
void setX (int x)

Share this post


Link to post
Share on other sites
Quote:
Original post by Hodgman
Quote:
Original post by iaminternets

void setX (const int x)
{
_x = x;
}

To whomever is calling this function, the fact that x is const doesn't change a thing (though if x weren't a simple non-reference int, that would be a different story). However, x is not going to be changed in the function, so semantically, it seems it should be const. What do you think?
You're passing by const-value. This is pointless as you're getting a copy of x and then promising to not modify the copy.

Setters should either pass by const-reference or pass by value:
void setX (const int& x)
void setX (int x)


Be fair; I made note of the fact that const int x means nothing to whomever is calling the function!

Semantically, I made x const because it isn't changed in the function, though I'm wondering whether it's not considered good practice.

As a side note, I didn't make x a reference because I don't see what it adds semantically (or performance-wise).

Share this post


Link to post
Share on other sites
I wouldn't use const just because something doesn't change, instead I use it to ensure that something doesn't change when the design dictates that it mustn't.
In this case, it doesn't matter if you change your local copy, so there is no need to enforce that constraint (over-engineering).

[edit] Sorry if my previous post seemed harsh - I didn't mean any offense, I was just trying to be factual.

[edit2] After working as a maintenance coder, I've come to see arguments such as "const int x" as a likely bug because it has no effect on the design (just as linux kernel coders have come to see "volatile" as an indicator of buggy code).
In many cases, it has turned out to be a typo and the author actually meant to use a const-reference ;)

[Edited by - Hodgman on March 12, 2009 8:19:34 PM]

Share this post


Link to post
Share on other sites
I agree with Hodgman here. A big part of your coding style should be used to help a reader of the code understand what you are trying to do. Implying that a parameter passed by value shouldn't be modified should mean that there's a reason for it which, in this case, there isn't one. This could be confusing. Someone reading the code would have to think, "Now why did they do that?". However, making a parameter that is passed by reference either const or non-const does confer your original intent (as well as enforce your intent in the code, but that's not my point here) and would be helpful to someone else reading the code.

Share this post


Link to post
Share on other sites
I personally leave the const out. In function declaration its better to leave it out.

For the definition of the function, as mentioned, it doesn't make difference to caller. That said, having const value parameter still has advantages. Analyzing code can become easier, as one doesn't have to "scan" the code to figure out if it is been changed. Same applies for defining local variables as const aswell.

So for the sake of clarity, I sometimes add the const.

Share this post


Link to post
Share on other sites
Const helps optimisations since the compiler knows in advance that the value won't change. (The compiler can analyse its use but with a load of inline methods and references being recursively thrown around it might not always be feasible to detect it.)

Const helps correctness since you are more clearly stating your intentions to yourself.

Const references in inline or inlinable functions are handy because it gives the compiler the option to copy-construct, which may or may not be more efficient.

Personally, I almost always use either const references or non-const pointers for input and output arguments respectively. Sure some of those const references are interchanable with copy-constructed objects, especially for builtins, but I say having ANY consistent style is better than NO consistent style(*), whichever style you choose.

(*) Apart from dumb, crappy styles (MS "Hungarian" I'm looking at you) and the inevitable exceptional circumstance.

Share this post


Link to post
Share on other sites
In your situation, don't use const. Pass by value. It doesn't matter, because even if you change the value of the parameter variable, the outside variable(the one passed to the function won't change).

Use const only with references.

1.

void y(const int &x)
{
}


2.

void y(int &x)
{
}


The difference here is that in 1, you can pass constant values as well.

y(10); // OK in 1, error in 2

Share this post


Link to post
Share on other sites
Quote:
The difference here is that in 1, you can pass constant values as well.

Or in a more general way, you can't pass a temporary as a non-const reference...

Share this post


Link to post
Share on other sites
I always pass int by non-const value because the semantics are simple and understood.
spraff is right, too, but I'm too lazy to write the extra stuff without achieving anything practical.
This one totally boils down to personal preference.
Quote:
JSF AV C++ CODING STANDARDS
AV Rule 116
Small, concrete-type arguments (two or three words in size) should be passed by value if changes made to formal parameters should not be reflected in the calling function.
Rationale: Pass-by-value is the simplest, safest method for small objects of concrete type. Note that non-concrete objects must be passed by pointer or reference to realize polymorphic behavior. See rules AV Rule 117 and AV Rule 118.

Share this post


Link to post
Share on other sites
I don't think the topic here is about whether to pass by value or by reference. I think the topic is, when you pass by value, is there advantages to make it const in function definition.


// .h
void dostuff(int x);

// .cpp
void dostuff(int const x)
{
// do stuff
}




For someone reading the declaration does not care about if there is const or not, becouse it doesn't make any difference. So its better to left out.

For someone reading the definition it might make things more clear. If there is a lot of stuff going on, I'd argue it's quicker and easier to analyze the function. Working memory has a capacity of around four to seven chunks simultaneously. Making stuff const that does not change, does simplify the function.

Edit: Umm, guess I didn't read the topic so well after all. For setters, which are one line functions, const only adds clutter. But for more complex functions I think there are benefits for const.

Share this post


Link to post
Share on other sites

I usually make all in-parameters const, even if passed by value.

Reasons:
- helps prevent goofy rhs = lhs type mistakes
- could feasibly improve optimizations on inline methods

I suppose it's a bit more typing, but that's hardly noticeable compared to my somewhat verbose class and variable names.

Share this post


Link to post
Share on other sites
As others have said before, const in an argument list is part of the contract between the caller and the callee - at least when applied to references and pointers. When applied to a value, it's merely a minutia of the internal implementation of the callee, which is of absolutely no concern to the caller and only serves to clutter up the contract.

Share this post


Link to post
Share on other sites
Quote:
Original post by Red Ant
As others have said before, const in an argument list is part of the contract between the caller and the callee - at least when applied to references and pointers. When applied to a value, it's merely a minutia of the internal implementation of the callee, which is of absolutely no concern to the caller and only serves to clutter up the contract.


Are you saying:

1. Variables that will never change should always be const unless they are in the parameter list of a function, or
2. Variables that will never change should always be const, and if they are in the parameter list of a function, they should be made references so as not to confuse whomever is calling the function?

Share this post


Link to post
Share on other sites
Quote:
Original post by spraff
Const helps optimisations since the compiler knows in advance that the value won't change. (The compiler can analyse its use but with a load of inline methods and references being recursively thrown around it might not always be feasible to detect it.)
Not as much as you'd think. Due to the difficulty of aliasing analysis, a compiler can't usually assume that any variable, const or not, will never change.

Quote:
Const helps correctness since you are more clearly stating your intentions to yourself.
Here, however, you are not stating your intentions to yourself, but to the person calling the function. What does he care if you intend to change your local variables?

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by spraff
Const helps optimisations since the compiler knows in advance that the value won't change. (The compiler can analyse its use but with a load of inline methods and references being recursively thrown around it might not always be feasible to detect it.)
Not as much as you'd think. Due to the difficulty of aliasing analysis, a compiler can't usually assume that any variable, const or not, will never change.

Quote:
Const helps correctness since you are more clearly stating your intentions to yourself.
Here, however, you are not stating your intentions to yourself, but to the person calling the function. What does he care if you intend to change your local variables?


Sneftel, does that mean you shouldn't state your intentions to yourself (or your coworkers) if someone else will be able to see those intentions?

Share this post


Link to post
Share on other sites
Quote:
Original post by iaminternets
Sneftel, does that mean you shouldn't state your intentions to yourself (or your coworkers) if someone else will be able to see those intentions?
Do you declare int variables within a function body as const, if you only write to them once? I doubt it, as it causes more trouble than it is worth - no one really cares whether or not a given variable is constant, and it only adds extra work if you discover a need to change it.

For reference arguments, const is important, as you may affect the caller (as well as yourself), but for value types it makes no difference one way or the other, and const is a waste.

Share this post


Link to post
Share on other sites
Quote:
Original post by iaminternets
Sneftel, does that mean you shouldn't state your intentions to yourself (or your coworkers) if someone else will be able to see those intentions?
It means that the standard convention is for function prototypes to be used solely to convey information of use to those calling the function.

Share this post


Link to post
Share on other sites
Quote:
Original post by iaminternets
Are you saying:

1. Variables that will never change should always be const unless they are in the parameter list of a function, or
2. Variables that will never change should always be const, and if they are in the parameter list of a function, they should be made references so as not to confuse whomever is calling the function?


Variables that will never change should always be const unless they are non-pointer, non-reference arguments in the parameter list of a function.

Share this post


Link to post
Share on other sites

This topic is 3199 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this