Can const-correctness improve performance?
const
correctness can't improve performance because const_cast
and mutable
are in the language, and allow code to conformingly break the rules. This gets even worse in C++11, where your const
data may e.g. be a pointer to a std::atomic
, meaning the compiler has to respect changes made by other threads.
That said, it is trivial for the compiler to look at the code it generates and determine if it actually writes to a given variable, and apply optimizations accordingly.
That all said, const
correctness is a good thing with respect to maintainability. Otherwise, clients of your class could break that class's internal members. For instance, consider the standard std::string::c_str()
-- if it couldn't return a const value, you'd be able to screw around with the internal buffer of the string!
Don't use const
for performance reasons. Use it for maintainability reasons.
Does declaring C++ variables const help or hurt performance?
const
is mainly a compile-time thing, however, declaring something as const
sometimes allows for certain optimizations. If the code in question isn't a performance bottleneck, I wouldn't worry about it and just use const
as intended: to produce clearer code and prevent yourself from doing stupid things.
Does const-correctness give the compiler more room for optimization?
[Edit: OK so this question is more subtle than I thought at first.]
Declaring a pointer-to-const or reference-of-const never helps any compiler to optimize anything. (Although see the Update at the bottom of this answer.)
The const
declaration only indicates how an identifier will be used within the scope of its declaration; it does not say that the underlying object can not change.
Example:
int foo(const int *p) {
int x = *p;
bar(x);
x = *p;
return x;
}
The compiler cannot assume that *p
is not modified by the call to bar()
, because p
could be (e.g.) a pointer to a global int and bar()
might modify it.
If the compiler knows enough about the caller of foo()
and the contents of bar()
that it can prove bar()
does not modify *p
, then it can also perform that proof without the const declaration.
But this is true in general. Because const
only has an effect within the scope of the declaration, the compiler can already see how you are treating the pointer or reference within that scope; it already knows that you are not modifying the underlying object.
So in short, all const
does in this context is prevent you from making mistakes. It does not tell the compiler anything it does not already know, and therefore it is irrelevant for optimization.
What about functions that call foo()
? Like:
int x = 37;
foo(&x);
printf("%d\n", x);
Can the compiler prove that this prints 37, since foo()
takes a const int *
?
No. Even though foo()
takes a pointer-to-const, it might cast the const-ness away and modify the int. (This is not undefined behavior.) Here again, the compiler cannot make any assumptions in general; and if it knows enough about foo()
to make such an optimization, it will know that even without the const
.
The only time const
might allow optimizations is cases like this:
const int x = 37;
foo(&x);
printf("%d\n", x);
Here, to modify x
through any mechanism whatsoever (e.g., by taking a pointer to it and casting away the const
) is to invoke Undefined Behavior. So the compiler is free to assume you do not do that, and it can propagate the constant 37 into the printf(). This sort of optimization is legal for any object you declare const
. (In practice, a local variable to which you never take a reference will not benefit, because the compiler can already see whether you modify it within its scope.)
To answer your "side note" question, (a) a const pointer is a pointer; and (b) a const pointer can equal NULL. You are correct that the internal representation (i.e. an address) is most likely the same.
[update]
As Christoph points out in the comments, my answer is incomplete because it does not mention restrict
.
Section 6.7.3.1 (4) of the C99 standard says:
During each execution of B, let L be any lvalue that has &L based on P. If L is used to
access the value of the object X that it designates, and X is also modified (by any means),
then the following requirements apply: T shall not be const-qualified. ...
(Here B is a basic block over which P, a restrict-pointer-to-T, is in scope.)
So if a C function foo()
is declared like this:
foo(const int * restrict p)
...then the compiler may assume that no modifications to *p
occur during the lifetime of p
-- i.e., during the execution of foo()
-- because otherwise the Behavior would be Undefined.
So in principle, combining restrict
with a pointer-to-const could enable both of the optimizations that are dismissed above. Do any compilers actually implement such an optimization, I wonder? (GCC 4.5.2, at least, does not.)
Note that restrict
only exists in C, not C++ (not even C++0x), except as a compiler-specific extension.
do const declarations help the compiler (GCC) produce faster code?
In general const
modifier on method, references and pointers can't be used to optimize code for a couple of reasons. The primary one is that const
modifier, in those contexts, doesn't make any guarantees about the underlying data not changing, it just makes it harder to modify it. Here is a classic example
void M(const C& p1, C& p2) {
cout << p1.field << endl;
p2.Mutate();
cout << p1.field<< endl;
}
In this case it's very possible that p1.field
is modified in this code. The most obvious case is that p1
and p2
refer to the same value.
C local;
M(local, local);
Hence there is no real optimization the compiler can do here. The const
parameter is equally as dangerous as the non-const one.
The other reason why it can't really optimize is that anyone can cheat in C++ with const_cast
.
class C {
public:
int field;
int GetField() const {
C* pEvil = const_cast<C*>(this);
pEvil->field++;
return field;
}
};
So even if you are dealing with a single const
reference the values are still free to change under the hood.
Does const call by reference improve performance when applied to primitive types?
My suspicion is that it is advantageous to use call-by-reference as soon as the primitive type's size in bytes exceeds the size of the address value. Even if the difference is small, I'd like to take the advantage because I call some of these functions quite often.
Performance tweaking based on hunches works about 0% of the time in C++ (that's is a gut feeling I have about statistics, it works usually...)
It is correct that the const T&
will be smaller than the T
if sizeof(T) > sizeof(ptr)
, so usually 32-bits, or 64, depending on the system..
Now ask yourself :
1) How many built-in types are bigger than 64 bits ?
2) Is not copying 32-bits worth making the code less clear ? If your function becomes significantly faster because you didn't copy a 32bit value to it, maybe it doesn't do much ?
3) Are you really that clever ? (spoiler alert : no.) See this great answer for the reason why it is almost always a bad idea :
https://stackoverflow.com/a/4705871/1098041
Ultimately just pass by value. If after (thorough) profiling you identify that some function is a bottleneck, and all of the other optimizations that you tried weren't enough (and you should try most of them before this), pass-by-const-reference.
Then See that it doesn't change anything. roll-over and cry.
What kind of optimization does const offer in C/C++?
Source
Case 1:
When you declare a const
in your program,
int const x = 2;
Compiler can optimize away this const
by not providing storage for this variable; instead it can be added to the symbol table. So a subsequent read just needs indirection into the symbol table rather than instructions to fetch value from memory.
Note: If you do something like:
const int x = 1;
const int* y = &x;
Then this would force compiler to allocate space for x
. So, that degree of optimization is not possible for this case.
In terms of function parameters const
means that parameter is not modified in the function. As far as I know, there's no substantial performance gain for using const
; rather it's a means to ensure correctness.
Case 2:
"Does declaring the parameter and/or the return value as const help the compiler to generate more optimal code?"
const Y& f( const X& x )
{
// ... do something with x and find a Y object ...
return someY;
}
What could the compiler do better? Could it avoid a copy of the parameter or the return value?
No, as argument is already passed by reference.
Could it put a copy of x or someY into read-only memory?
No, as both x
and someY
live outside its scope and come from and/or are given to the outside world. Even if someY
is dynamically allocated on the fly within f()
itself, it and its ownership are given up to the caller.
What about possible optimizations of code that appears inside the body of f()? Because of the const, could the compiler somehow improve the code it generates for the body of f()?
Even when you call a const member function, the compiler can't assume that the bits of object x
or object someY
won't be changed. Further, there are additional problems (unless the compiler performs global optimization): The compiler also may not know for sure that no other code might have a non-const reference that aliases the same object as x
and/or someY
, and whether any such non-const references to the same object might get used incidentally during the execution of f();
and the compiler may not even know whether the real objects, to which x
and someY
are merely references, were actually declared const in the first place.
Case 3:
void f( const Z z )
{
// ...
}
Will there be any optimization in this?
Yes because the compiler knows that z
truly is a const object, it could perform some useful optimizations even without global analysis. For example, if the body of f()
contains a call like g( &z )
, the compiler can be sure that the non-mutable parts of z
do not change during the call to g()
.
How does const correctness help write better programs?
A whole section is devoted to Const Correctness in the FAQ. Enjoy!
Is it worth to insert `const`-correctness
Should I invest the amount of time to introduce
const
-correctness into this code?
If you feel that you can get it all done in a reasonable time, sure. const
-correctness is a good thing, so if you can adjust the codebase to employ it properly then that can never be bad.
It all comes down to how much time you have available and what else you could be doing instead, which is more about project management and more appropriate on programmers.SE.
Even worse, I have to touch and alter the old mature code and explain to the seniors what I did during the code review. Is it worth it?
It's certainly worth it for them (and, by extension, to everybody else). It sounds like they will learn a lot in code review, which is fantastic!
Edit
As molbdnilo rightly points out, this is a big change and you should definitely have a group discussion about it before starting. This would be more appropriate than leaving it to code review in two weeks' time, when you've already done it.
Should I use const for local variables for better code optimization?
Or am I wrong, and compilers can figure out by themselves that the local variable is never modified?
Most of the compilers are smart enough to figure this out themselves.
You should rather use const
for ensuring const-correctness and not for micro-optimization.
const correctness lets compiler help you guard against making honest mistakes, so you should use const
wherever possible but for maintainability reasons & preventing yourself from doing stupid mistakes.
It is good to understand the performance implications of code we write but excessive micro-optimization should be avoided. With regards to performance one should follow the,
80-20 Rule:
Identify the
20%
of your code which uses80%
of your resources, through profiling on representative data sets and only then attempt to optimize those bottlenecks.
Sell me on const correctness
This is the definitive article on "const correctness": https://isocpp.org/wiki/faq/const-correctness.
In a nutshell, using const is good practice because...
- It protects you from accidentally changing variables that aren't intended be changed,
- It protects you from making accidental variable assignments, and
The compiler can optimize it. For instance, you are protected from
if( x = y ) // whoops, meant if( x == y )
At the same time, the compiler can generate more efficient code because it knows exactly what the state of the variable/function will be at all times. If you are writing tight C++ code, this is good.
You are correct in that it can be difficult to use const-correctness consistently, but the end code is more concise and safer to program with. When you do a lot of C++ development, the benefits of this quickly manifest.
Related Topics
Static Constexpr Odr-Used or Not
Why Is F(I = -1, I = -1) Undefined Behavior
Is a '=Default' Move Constructor Equivalent to a Member-Wise Move Constructor
What Is a Scalar Object in C++
How to Create a Dll with Swig from Visual Studio 2010
How Do Traits Classes Work and What Do They Do
What Are Near, Far and Huge Pointers
Random Number Generator That Produces a Power-Law Distribution
Public Virtual Function Derived Private in C++
Global Function Definition in Header File - How to Avoid Duplicated Symbol Linkage Error
C++ How Is Release-And-Acquire Achieved on X86 Only Using Mov
How to Print to Console When Using Qt
Differencebetween a Static and Const Variable
Receiving Rtsp Stream Using Ffmpeg Library
Sizeof Class with Int , Function, Virtual Function in C++