Use const wherever possible in C++?
C++ FAQ:
If you find ordinary type safety helps you get systems correct (it
does; especially in large systems), you'll find const correctness
helps also.
You should use const
when you want to be sure not to change variable accidentally or intentionally. Some constants (globals and class static, strings & integers, but not variables with nontrivial constructor) can be placed in read-only parts of the executable, therefore result in segmentation fault if you try to write to it.
You should be explicit using const
as a specifier on functions that follow this principle as well as on function arguments. If you don't have to change actual argument, make it const
. This doesn't limit the possible usages of such function, but extends them, because now they might be used on const
arguments, and on const
objects.
In declaration
const int* foo(const int* const&) const;
every const
means something different and yes, obviously it should be used if it is needed.
Summary
Using const
increases type-safety of your program.
C++ FAQ:
[18.3] Should I try to get things const correct "sooner" or "later"?
At the very, very, very beginning.
Should I use the 'const' keyword in c++
Yes, you should make all variables const
if you are never going to change its value after initialization. This prevents bugs where you accidentally change a value you're not supposed to. You seem to be aware of this already.
In addition, there is something that you might not be aware of, which is that making an int
variable const
also makes it a constant-expression, so long as the initializer itself is also a constant-expression, e.g. the int
literal 56
. This allows you to use it in contexts where you need a constant-expression, e.g. as the dimension of a static array:
const int size = 56;
int a[size]; // ok
int size = 56;
int a[size]; // error
What's the correct way to use const in C++?
Where you use const
depends on the purpose of the function. As James suggests in his comment (which is worth putting as an answer), put const
anywhere you can:
If the function is intended to modify state within it's object instance, don't put const
at the end of the signature.
If the function is intended to modify one of it's reference or pointer parameters, don't put const
on the parameter.
If the variable referenced by a pointer or reference should be modified, don't put const
on the type (remember, const
applies to the part of the definition immediately prior).
If the returned reference/pointer references a variables that should not be changed by the received, do put const
on the type.
Answering the examples given in the question is impossible without knowing the purpose of the functions. My tendency would be to use string ToString() const
and char* ToString() const
, with very clear documentation on who is responsible for delete
ing the char*
.
As an extra note, const char*
and char const*
are identical (pointer to unmodifiable characters). char* const
, on the other hand, is an unmodifiable pointer to modifiable characters.
C++ const keyword - use liberally?
This, IMHO, is overusing.
When you say 'const int age,...' what you actually say is "you can't change even the local copy inside your function". What you do is actually make the programmer code less readable by forcing him to use another local copy when he wants to change age/pass it by non-const reference.
Any programmer should be familiar with the difference between pass by reference and pass by value just as any programmer should understand 'const'.
Why should I not use `const` in this simple function?
From the caller's perspective, both the first and the second form are the same.
Since the integers are passed by value, even if the function modifies a
and b
, the modified values are copies of the original and won't be visible to the caller.
However, from the function implementer's perspective there's a difference. In fact, in the second form:
int add(const int a, const int b)
you will get a compiler error if you try to modify the values of a
and b
inside the function's body, as they are marked as const
.
Instead, you can change those values if you omit the const
.
Again, those modifications will not be visible to the caller.
When to use const and const reference in function args?
Asking whether to add const is the wrong question, unfortunately.
Compare non-const ref to passing a non-const pointer
void modifies(T ¶m);
void modifies(T *param);
This case is mostly about style: do you want the call to look like call(obj)
or call(&obj)
? However, there are two points where the difference matters. If you want to be able to pass null, you must use a pointer. And if you're overloading operators, you cannot use a pointer instead.
Compare const ref to by value
void doesnt_modify(T const ¶m);
void doesnt_modify(T param);
This is the interesting case. The rule of thumb is "cheap to copy" types are passed by value — these are generally small types (but not always) — while others are passed by const ref. However, if you need to make a copy within your function regardless, you should pass by value. (Yes, this exposes a bit of implementation detail. C'est le C++.)
Compare const pointer to non-modifying plus overload
void optional(T const *param=0);
// vs
void optional();
void optional(T const ¶m); // or optional(T param)
This is related to the non-modifying case above, except passing the parameter is optional. There's the least difference here between all three situations, so choose whichever makes your life easiest. Of course, the default value for the non-const pointer is up to you.
Const by value is an implementation detail
void f(T);
void f(T const);
These declarations are actually the exact same function! When passing by value, const is purely an implementation detail. Try it out:
void f(int);
void f(int const) {/*implements above function, not an overload*/}
typedef void C(int const);
typedef void NC(int);
NC *nc = &f; // nc is a function pointer
C *c = nc; // C and NC are identical types
When, if ever, should we use const?
I believe the only time "const" is appropriate is when there is a spec that you're coding against that is more durable than the program you're writing. For instance, if you're implementing the HTTP protocol, having a const member for "GET" is appropriate because that will never change, and clients can certainly hard-code that into their compiled apps without worrying that you'll need to change the value later.
If there's any chance at all you need to change the value in future versions, don't use const.
Oh! And never assume const is faster than a readonly field unless you've measured it. There are JIT optimizations that may make it so it's actually exactly the same.
Passing const reference parameters whenever possible
Why didn't they make
char c
aconst
reference parameter?
char
is so small, it's generally cheaper to pass it by value rather than by reference (const
or otherwise).
Related Topics
Reading Files Larger Than 4Gb Using C++ Stl
Fatal Error C1083: Cannot Open Include File: 'Xyz.H': No Such File or Directory
What Does the "::" Mean in "::Tolower"
Handling Ssl_Shutdown Correctly
Std::Optional - Construct Empty with {} or Std::Nullopt
Exporting Static Data in a Dll
Clion C++ Can't Read/Open .Txt File in Project Directory
Does Gcc Inline C++ Functions Without the 'Inline' Keyword
Opencv Gtk+2.X Error - "Unspecified Error (The Function Is Not Implemented...)"
Unit Test That a Class Is Non Copyable, and Other Compile-Time Properties
The Cxx Compiler Identification Is Unknown
Conditionally Replace Regex Matches in String
Memoized, Recursive Factorial Function
Drawing in a Win32 Console on C++
Will I Be Able to Declare a Constexpr Lambda Inside a Template Parameter