Return static const value - c++

Is declaring static const array inside getter function is reasonable way of keeping code coherent? I never saw it before, but in code review I found something like this:
static const std::array<std::string, 4>& fooArrayGetter()
{
static const std::array<std::string, 4> fooArray =
{"foo" ,"bar", "baz", "qux"};
return fooArray;
}
It looks correct: array is allocated only once, quite elegant because getter is combined with its value, but running it inside Godbolt https://godbolt.org/z/K8Wv94 gives really messy assembler comparing to making whole operation in more standard way. As a motivation for this code I received reference to Item 4 from Meyers' Efficient C++
Edit: GCC compiler with --std=c++11 flag

Is declaring static const array inside getter function is reasonable way of keeping code coherent?
It can be. It can also be unnecessarily complicated if you don't need it. Whether there is a better alternative depends on what you intend to do with it.
gives really messy assembler
Messiness of non-optimised assembly rarely matters.

Warning
static keyword here has two different meanings!
This which you thing applies to return value says: function fooArrayGetter should be visible only in this translation unit (only current source code can use this function)! This doesn't have any impact on return value type!
this inside a function says: variable fooArray has lifetime like a global scope (it is initialized on first use of fooArrayGetter and lives as long as application). This static makes returning a const reference a safe thing to do since makes this variable/constant ethernal.

Related

Can the compiler not determine whether a variable is const by Itself?

I know for a function this simple it will be inlined:
int foo(int a, int b){
return a + b;
}
But my question is, can't the compiler just auto-detect that this is the same as:
int foo(const int a, const int b){
return a + b;
}
And since that could be detected, why would I need to type const anywhere? I know that the inline keyword has become obsolete because of compiler advances. Isn't it time that const do the same?
You don't put const as the result of not modifying a variable. You use const to enforce you not modifying it. Without const, you are allowed to modify the value. With const, the compiler will complain.
It's a matter of semantics. If the value should not be mutable, then use const, and the compiler will enforce that intention.
Yes, the compiler can prove constness in your example.
No, it would be of no use :-).
Update: Herb Sutter dedicated one of his gotchas to the topic (http://www.gotw.ca/gotw/081.htm). Summary:
const helps most by making the compiler and linker choose functions for const objects including const member functions which can be coded to be more efficient.
const doesn't help with the usual translation unit model [differs from what I supposed]; the compiler needs to see the whole program for verifying factual constness (which the mere declaration does not guarantee) and exploiting it, as well as prove the absence of aliasing ...
... and when the compiler can see the whole program and can prove factual constness it actually of course doesn't need the const declaration any longer! It can prove it. Duh.
The one place where const makes a big difference is a definition because the compiler may store the object in read-only memory.
The article is, of course, worth reading.
With respect to whole program optimization/translation which usually is necessary to exploit constness cf. the comments below from amdn and Angew.
can't the compiler just auto-detect that this is the same as...
If by that you mean whether the compiler can detect that the variables are not modified in the second case, most likely yes. The compiler is likely to produce the same output for both code samples. However, const might help the compiler in more complex situations. But the most important point is that it keeps you from inadvertently modifying one of the variables.
The compiler will always know what you did and will infer internal constness from that in order to optimize the code.
What the compiler can never know is what you wanted to do.
If you wanted a variable to remain constant but accidentally change it later in the code the compiler can only trap this error if you tell the compiler what you wanted.
This is what the const keyword is for.
struct bar {
const int* x;
};
bar make_bar(const int& x){
return {&x};
}
std::map<int,bar> data;
shuffle(data);
knowing that bar will never modify x (or cause it to be modified) in its lifetime requires understanding every use of bar in the program, or, say, making x a pointer to const.
Even with perfect whole program optimization (which cannot exist: turing machines are not perfectly understandable), dynamic linking means you cannot know at compile time how data will be used. const is a promise, and breaking that promise (in certain contexts) can be UB. The compiler can use that UB to optimize in ways that ignores the promise being broken.
inline is not obsolete: it means the same thing it ever did, that linker collisions of this symbol are to be ignored, and it mildly suggests injecting the code into the calling scope.
const simplifies certain optimizations (which may make them possible), and enforces things on the programmer (which helps the programmer), and can change what code means (const overloading).
Maybe he could but the const statement is also for you. If you set a variable as const and try to assign a new value afterwards you will get an error. If the compiler would make a var out of it by himself this would not work.
Const qualifier is a method to enforce behavior of the variables inside your scope. It only provides the compiler the means to scream at you if you try to modify them inside the scope where they are declared const.
A variable might be truly const (meaning it is writen in a read only location, hence compiler optimizations) if it's const at the time of it's declaration.
You can provide your 2nd function non const variables who will become "const" inside the function scope.
Or alternativelly you can bypass the const by casting , so the compiler cannot parse your whole code in an attempt to figure out if the valuea will be changed or not inside the function scope.
Considering that const qualifiers are mainly for code enforcing, and that compilers will generate the same code in 99% of cases if a variable is const or non const, then NO, the compiler shouldn't auto-detect constness.
Short answer: because not all problems are that simple.
Longer answer: You cannot assume that an approach which works with a simple problem also works with a complex problem
Exact answer: const is an intent. The main goal of const is to prevent you doing anything accidentially. If the compiler would add const automatically it would just see that the approach is NOT const and leave it at it. Using the const keyword will raise an error instead.

do "const" declarations help the compiler (GCC) produce faster code? [duplicate]

This question already has answers here:
Does const-correctness give the compiler more room for optimization?
(7 answers)
Closed 9 years ago.
Do const declarations help the compiler (GCC) produce faster code or are they only useful for readability and correctness?
Zed Shaw has argued that const is useless or is overused in C/C++:
Next is all the bizarre fascination with const. For some odd reason
C++ loves to make you slap const on every part of a declaration, and
yet I get the same end result as C: a function is called. (...)
(From: http://librelist.com/browser//mongrel2/2010/7/15/c-verses-c++/#770d94bcfc6ddf1d8510199996b607dd )
Yes. Here’s one concrete example. const makes it possible to pass arguments by const& rather than by value (which might require a costly copy). It’s important to realise that the alternative to pass-by-const& is not pass-by-& because the latter doesn’t allow temporaries to be bound. So, for instance, this code:
auto result = foo{1} + foo{2} + foo{3};
may call foo operator +(foo const&, foo const&) but it may not call foo operator +(foo&, foo&).
That way, const helps avoid copies.
But generally, const is a tool to ensure correctness, not to to aid optimisations.
Either way, Zed Shaw has no idea what he’s talking about. The rest of his rant is similarly misinformed, by the way.
No, const does not help the compiler make faster code. Const is for const-correctness, not optimizations.
The C++ standard says that const items can't be modified, but also says that const_cast should remove the const modifier from an object and make it writable (unless it's located in actually read-only memory, in which case the behavior is undefined); as such const cannot mean, in general, that the target variable will not change.
I can only think of these two very narrow scenarios where having const produces faster code than not having it:
the variable is global with internal linkage (static) and is passed by reference or pointer to a function defined in a different translation unit (different file). In this case, the compiler cannot elide reads to it if it is not marked const;
the variable is global with external linkage (extern). Reads to a const extern can be elided inside the file that defines it (but nowhere else).
When const is applied to a global variable, the compiler is allowed to assume that the value will never change because it will place it in read-only memory, and this means undefined behavior if the program attempts to modify it, and compiler authors love to rely on the threat of undefined behavior to make code faster.
Note that both scenarios apply only to global variables, which probably make for a very minor portion of the variables in your program. To its merit, however, const implies static at the global level in C++ (this is not the case in C).
Someone above said that using const can make code faster because it's possible to use const references. I would argue here that what make the code faster is the use of a reference, not the use of const.
That said, I still believe const is a very sharp knife with which you can't cut yourself and I would advise that you use it whenever it's appropriate, but don't do it for performance reasons.
Yes, const can (not guaranteed) help the compiler produce faster/more correct code. More so than not, they're just a modifier on data that you express to both the compiler and to other people that read your code that some data is not supposed to change. This helps the type system help you write more correct software.
More important than optimizations, they just prevent your own code and people using your code from writing to data you assume to be invariant.
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.

Should I use const for local variables for better code optimization?

I often use const for local variables that are not being modified, like this:
const float height = person.getHeight();
I think it can make the compiled code potentially faster, allowing the compiler to do some more optimization. Or am I wrong, and compilers can figure out by themselves that the local variable is never modified?
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 uses 80% of your resources, through profiling on representative data sets and only then attempt to optimize those bottlenecks.
This performance difference will almost certainly be negligible, however you should be using const whenever possible for code documentation reasons. Often times, compilers can figure this out for your anyway and make the optimizations automatically. const is really more about code readability and clarity than performance.
If there is a value type on the left hand, you may safely assume that it will have a negligible effect, or none at all. It's not going to influence overload resolution, and what is actually const can easily be deduced from the scope.
It's an entirely different matter with reference types:
std::vector<int> v(1);
const auto& a = v[0];
auto& b = v[0];
These two assignments resolve to two entirely different operators, and similar overload pairs are found in many libraries aside STL too. Even in this simple example, optimizations which depend on v having been immutable for the scope of b are already no longer trivial and less likely to be found.
The STL is still quite tame in these terms though, in such that at least the behavior doesn't change based on choosing the const_reference overload or not. For most of STL, the const_reference overload is only tied to the object being const itself.
Some other libraries (e.g. Qt) make heavy use of copy-on-write semantics. In these const-correctness with references is no longer optional, but necessary:
QVector<int> v1(1);
auto v2 = v1; // Backing storage of v2 and v1 is still linked
const auto& a = v1[0]; // Still linked
const auto& b = v2[0]; // Still linked
auto& c = v2[0]; // Deep copy from v1 to v2 is happening now :(
// Even worse, &b != &c
Copy-on-write semantics are something commonly found in large-matrix or image manipulation libraries, and something to watch out for.
It's also something where the compiler is no longer able to save you, the overload resolution is mandated by C++ standard and there is no leeway for eliminating the costly side effects.
I don't think it is a good practice to make local variables, including function parameters, constant by default.
The main reason is brevity. Good coding practices allow you to make your code short, this one doesn't.
Quite similarly, you can write void foo(void) in your function declarations, and you can justify it by increased clarity, being explicit about not intending to pass a parameter to the function, etc, but it is essentially a waste of space, and eventually almost fell out of use. I think the same thing will happen to the trend of using const everywhere.
Marking local variables with a const qualifier is not very useful for most of the collaborators working with the code you create. Unlike class members, global variables, or the data pointed to a by a pointer, a local variable doesn't have any external effects, and no one would ever be restricted by the qualifier of the local variable or learn anything useful from it (unless he is going to change the particular function where the local variable is).
If he needs to change your function, the task should not normally require him to try to deduce valuable information from the constant qualifier of a variable there. The function should not be so large or difficult to understand; if it is, probably you have more serious problems with your design, consider refactoring. One exception is functions that implement some hardcore math calculations, but for those you would need to put some details or a link to the paper in your comments.
You might ask why not still put the const qualifier if it doesn't cost you much effort. Unfortunately, it does. If I had to put all const qualifiers, I would most likely have to go through my function after I am done and put the qualifiers in place - a waste of time. The reason for that is that you don't have to plan the use of local variables carefully, unlike with the members or the data pointed to by pointers.
They are mostly a convenience tool, technically, most of them can be avoided by either factoring them into expressions or reusing variables. So, since they are a convenience tool, the very existence of a particular local variable is merely a matter of taste.
Particularly, I can write:
int d = foo(b) + c;
const int a = foo(b); int d = a + c;
int a = foo(b); a += c
Each of the variants is identical in every respect, except that the variable a is either constant or not, or doesn't exist at all. It is hard to commit to some of the choices early.
There is one major problem with local constant values - as shown in the code below:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
// const uint32_t const_dummy = 0;
void func1(const uint32_t *ptr);
int main(void) {
const uint32_t const_dummy = 0;
func1(&const_dummy);
printf("0x%x\n", const_dummy);
return EXIT_SUCCESS;
}
void func1(const uint32_t *ptr) {
uint32_t *tmp = (uint32_t *)ptr;
*tmp = 1;
}
This code was compiled on Ubuntu 18.04.
As you can see, const_dummy's value can be modified in this case!
But, if you modify the code and set const_dummy scope to global - by commenting out the local definition and remove the comment from the global definition - you will get an exception and your our program will crash - which is good, because you can debug it and find the problem.
What is the reason? Well global const values are located in the ro (read only) section of the program. The OS - protects this area using the MMU.
It is not possible to do it with constants defined in the stack.
With systems that don't use the MMU - you will not even "feel" that there is a problem.

Volatile keyword allows access to const structures in UnitTest++

I'm using the UnitTest++ framework to implement unit tests on some C code I'm responsible for. The end product is embedded and uses const structures to hold configuration information. Since the target host can modify the configuration asynchronously the members of the structure are all volatile. Some of the structures are also declared as volatile.
I'm getting segmentation faults when I use const_cast to try to modify the structure instances lacking the volatile keyword on the UnitTest Windows 7 host. This makes sense to me. However, if the structure instance was declared with the volatile keyword then the test passes. This does not make sense to me.
Here's a quick code example that shows the problem with gcc on Win7. Switching the define value causes the segfault to appear or not, depending on if the volatile instance of the struct is used or not.
typedef struct
{
volatile int foo;
volatile int bar;
} TestStruct;
const TestStruct constStruct = { 1, 2};
volatile const TestStruct volatileConstStruct = { 3, 4};
#define SEG_FAULT 0
int main(void)
{
TestStruct * constPtr = const_cast<TestStruct*>(&constStruct);
TestStruct * constVolPtr = const_cast<TestStruct*>(&volatileConstStruct);
#if(SEG_FAULT == 0)
constVolPtr->foo = 10;
#else
constPtr->foo = 20;
#endif
}
Can anyone help me understand why the volatile keyword presents a workaround for the segfault? Also, can anyone suggest a method to allow me to modify the values in the structure for unit test without adding the volatile keyword to all the structure instances?
EDIT:
I've just discovered that you can do this in C:
#define const
Including the effective "const undefine" above in the test fixture allows my target compiler to see the const keyword and correctly place the structures into flash memory. However, the preprocessor on the UnitTest++ compiler strips out the const keyword, so my test fixture is able to modify the struct.
The drawback to this solution is that I cannot add unit tests that verify correct const operation of function calls. However, since removing the const from the struct instances is not an option (need the data to be placed in flash) this appears to be a drawback I will have to live with.
Why this strange behavior?
Modifying a const object using const_cast is an Undefined Behavior.
const_cast is used when you have a const pointer to an non const object and you want to point your pointer to it.
Why it works with volatile?
Not sure. However, It is still an Undefined Behavior and you are just lucky that it works.
The problem with Undefined Behavior is that all safe bets are off and the program might show any behavior. It might appear to work or it may not work. may crash or show any weird behavior.
it is best to not write any code exhibiting Undefined Behavior, that saves warranting explanations for such situations.
How to solve this?
Don't declare the objects you modify as const, Since you intend to modify them during the course of your program/test, they should not be const. Currently, You are making a promise to the compiler that your structure objects are immutable(const) but later you break that contract by modifying it. Make this promise only if you can keep it.
I believe a footnote in the standard gives you the answer. (Note that footnotes are not normative.)
In §6.7.3 of the standard draft N1570:
132) The implementation may place a const object that is not volatile
in a read-only region of storage.
This mean that the structure defined with the volatile keyword will be placed in read-write memory, despite the fact that it's defined const.
One could argue that the compiler is not allowed to place any of the structures in read-only memory, as they both contains volatile members. I would send in a compiler bug report, if I were you.
Can anyone help me understand why the volatile keyword presents a
workaround for the segfault? Also, can anyone suggest a method to
allow me to modify the values in the structure for unit test without
adding the volatile keyword to all the structure instances?
You can't. A const object is placed in read-only memory, and you will trigger a segfault if you write to it. Either drop the const or add volatile -- I would strongly recommend dropping const.

Function and declaring a local variable

Just having an conversation with collegue at work how to declare a variables.
For me I already decided which style I prefer, but maybe I wrong.
"C" style - all variable at the begining of function.
If you want to know data type of variable, just look at the begining of function.
bool Foo()
{
PARAM* pParam = NULL;
bool rc;
while (true)
{
rc = GetParam(pParam);
... do something with pParam
}
}
"C++" style - declare variables as local as possible.
bool Foo()
{
while (true)
{
PARAM* pParam = NULL;
bool rc = GetParam(pParam);
... do something with pParam
}
}
What do you prefer?
Update
The question is regarding POD variables.
The second one. (C++ style)
There are at least two good reasons for this:
This allow you to apply the YAGNI principle in the code, as you only declare variable when you need them, as close as possible to their use. That make the code easier to understand quickly as you don't have to get back and forth in the function to understand it all. The type of each variable is the main information about the variable and is not always obvious in the varaible name. In short : the code is easier to read.
This allow better compiler optimizations (when possible). Read : http://www.tantalon.com/pete/cppopt/asyougo.htm#PostponeVariableDeclaration
If due to the language you are using you are required to declare variables at the top of the function then clearly you must do this.
If you have a choice then it makes more sense to declare variables where they are used. The rule of thumb I use is: Declare variables with the smallest scope that is required.
Reducing the scope of a variable prevents some types errors, for example where you accidentally use a variable outside of a loop that was intended only to be used inside the loop. Reducing the scope of the variable will allow the compiler to spot the error instead of having code that compiles but fails at runtime.
I prefer the "C++ style". Mainly because it allows RAII, which you do in both your examples for the bool variable.
Furthermore, having a tight scope for the variable provides the compile better oppertunities for optimizations.
This is probably a bit subjective.
I prefer as locally as possible because it makes it completely clear what scope is intended for the variable, and the compiler generates an error if you access it outside the intended useful scope.
This isn't a style issue. In C++, non-POD types will have their constructors called at the point of declaration and destructors called at the end of the scope. You have to be wise about selecting where to declare variables or you will cause unnecessary performance issues. For example, declaring a class variable inside a loop may not be the wisest idea since constructor/destructor will be called every iteration of the loop. But sometimes, declaring class variables at the top of the function may not be the best if there is a chance that variable doesn't get used at all (like a variable is only used inside some 'if' statement).
I prefer C style because the C++ style has one major flaw to me: in a dense function it is very hard on eyes to find the declaration/initialization of the variable. (No syntax highlighting was able yet to cope reliably and predictably with my C++ coding hazards habits.)
Though I do adhere to no style strictly: only key variables are put there and most smallish minor variables live within the block where they are needed (like bool rc in your example).
But all important key variables in my code inevitably end up being declared on the top. And if in a nested block I have too much local variables, that is the sign that I have to start thinking about splitting the code into smaller functions.