This question is inspired by a question about final
in
java.
In C/C++, should I use const
whenever possible?
I know there is already a related question about using const
in parameters. Unfortunately that question and it's answers don't fully answer my question, because it's only about function parameters, but I would also like to know about other cases (eg: local variables).
Also, almost all answers to that question say we should use const
because it contains useful information about the accessibility of variables. But this seems to conflict with an answer about using final in Java which states final
may be superfluous if it doesn't contain extra information and so it should be omitted to keep the code short and clean.
So, should I use const
whenever possible? If so, why is the advice for const
in C++ different from the advice for final
in Java?
5 Answers 5
First of all, since you referenced Java's final
, that is a totally different beast than const
. Final means the reference cannot change, but says nothing about mutability. Const goes further by saying "a const reference cannot mutate" which is a much stronger guarantee. To do this in Java, internal state must be final and determined at construction time. Const is a lot easier to use, and an existing object can be "promoted" into a const reference.
Yes, you should use const whenever possible. It makes a contract that your code will not change something. Remember, a non-const variable can be passed in to a function that accepts a const parameter. You can always add const, but not take it away (not without a const cast which is a really bad idea).
Const-correctness may be tedious at times, but it helps guarantee immutability. This is crucial in multi-threaded code where threads share objects. It makes certain tasks more efficient: instead of copying state, just reuse the same immutable object. Libraries might accept const parameters in order to provide a guarantee to the programmer that no, your object will not change in an unpredictable way in the black hole that is the library's guts.
-
1Up vote because you explain that
final
andconst
do not have the same guarantees.Bill Door– Bill Door2016年10月05日 04:31:31 +00:00Commented Oct 5, 2016 at 4:31 -
3Constness is about writeability, not about mutability.Basilevs– Basilevs2016年10月05日 09:45:32 +00:00Commented Oct 5, 2016 at 9:45
-
6What happens if you write to a const reference? A compile time error. What happens if you write to the object that is referenced somewhere by const reference via another non-const reference? It mutates. Immutable object can't mutate, hence const refernce does not necessarily reference immutable object.Basilevs– Basilevs2016年10月05日 15:45:49 +00:00Commented Oct 5, 2016 at 15:45
-
1@Basilevs your observation only applies with const refs. If an object itself is declared const (not just the reference) then it it is more-or-less immutable (unless someone nefariously casts away the constness).Matthew James Briggs– Matthew James Briggs2016年11月08日 05:36:25 +00:00Commented Nov 8, 2016 at 5:36
-
1@Snowman an object can very definitely be const.
const int i = 1;
is an object that is neither a reference nor a pointer, and it is constCaleth– Caleth2017年08月30日 08:41:35 +00:00Commented Aug 30, 2017 at 8:41
Personally, const
takes me very little time to write, and very little time to read, usually much less than it takes to check whether any code mutates the variable, and it actually prevents me from writing bugs (anyone ever incremented their end iterator by accident? Etc)
I also find that being strict about const usage guides me towards better code in other ways, like creating helper functions to do non-trivial initialization.
I'm going to disagree with the other posters and recommend you don't use top-level const
on local variables and parameters. (References and pointers to const, i.e. const T&
, are different, and you should use them for correctness at all times when it's appropriate.)
The advantages of top-level const
are:
- Makes it clear that the local variables are not meant to be mutated.
- Gives a compiler error if you accidentally do attempt to mutate them.
The disadvantages are:
- Visual clutter.
Cannot be used on "pseudo-const" variables, i.e. variables that are initialized in some manner more complicated than direct construction, but not modified after, e.g. using
getline
:std::string line; // cannot be const std::getline(std::cin, line); // line should be const from here on out
Prevents move-out optimization on function call and return:
std::string f1(); std::string f2(std::string s); std::string f3() { const std::string s = f1(); // s is not meant to be modified // but I still want the move optimization here: const std::string result = f2(std::move(s)); // this doesn't move // and I want the compiler to move out here: return result; // this will probably RVO, but if not, the move // constructor will not be used due to the const }
I have worked on a codebase where local const
was used a lot, and I found it not helpful at all, yet it filled the code with subtle pessimizations as above. I personally prefer to adopt a general policy of modifying variables as rarely as possible, and making functions small enough that the usage of a variable is obvious, and even if it is modified, the complexity of the function is low enough to make it a non-issue.
-
2Your point about move-from is showing where you are not using the local in a const manner, as you (intend to) modify it with the moveCaleth– Caleth2016年10月25日 11:54:28 +00:00Commented Oct 25, 2016 at 11:54
-
1@Caleth No, that's the point. I don't intend to modify it. I just want to pass the value, or return it, and I want it to be efficient. Conceptually, the modification is just an optimization, which is not meant to be observable (since the variables aren't used afterwards). Practically, yes, there's a modification, since C++ doesn't have true destructive moves (like Rust has). That's exactly why I don't want
const
on locals: because it prevents technical modifications, not just conceptual modifications.Sebastian Redl– Sebastian Redl2016年10月25日 13:11:32 +00:00Commented Oct 25, 2016 at 13:11 -
2You don't want to modify the value, but you do want to modify the variable. You can instead use const& instead, and modify neitherCaleth– Caleth2016年10月25日 13:57:46 +00:00Commented Oct 25, 2016 at 13:57
-
Your pseudo-const can be rewritten using an immediately-invoked lambda:
const auto line = [&]{ std::string r; std::getline(std::cin, r); return r; }();
The technique is generally applicable even beyond this, but a bit more convoluted than the original. Still, better than a comment, and the extra enforcement by the compiler might be ample compensation.Deduplicator– Deduplicator2021年09月16日 16:55:35 +00:00Commented Sep 16, 2021 at 16:55
The const
keyword should be used for local variables, just like parameters. It's useful because:
- Easier to read the code. When someone reads the variable declaration, she knows it won't change. One less thing to worry while reading your code.
- Prevent you accidentally modify the variable
- No runtime penalty, everything is checked statically. It's like a free lunch,
const
should take just a second to write, so it's no big deal. - It's always a good idea to make your variables/parameters in your multi-threaded applications. Even your application is not multi-threaded, it's still a good habit.
- You give an opportunity for your C++ compiler to optimize your code.
Note that there's no right/wrong answer here. In your link, the answerer who had the most upvotes argued final
shouldn't be used locally. However, the next answerer strongly recommended it.
If your function is simple and trivial, you shouldn't add const
because everyone understands your intention. However, if the logic in your function is non-trivial, you should use the keyword. Remember, there is little to lose.
For what it's worth, the Google C++ Style Guide says,
Using
const
on local variables is neither encouraged nor discouraged.
-
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.2021年09月16日 15:38:01 +00:00Commented Sep 16, 2021 at 15:38
-
2I think it’s quite clear. Google says: Do whatever you prefer.gnasher729– gnasher7292021年09月18日 16:50:32 +00:00Commented Sep 18, 2021 at 16:50
-
Does anyone know the reason, why Google neither encourages nor discourages? Why not to say: "mark local variables as const whenever you can"?mercury0114– mercury01142023年01月27日 08:47:15 +00:00Commented Jan 27, 2023 at 8:47
-
There is a cost/benefit tradeoff to adding
const
. The cost is that it adds more characters to the code. Google essentially abstained from making a judgment on this tradeoff.dshin– dshin2023年01月27日 21:14:22 +00:00Commented Jan 27, 2023 at 21:14