I have an hpp file with following code:
const float PixelsPerMeter = ConfigManager->Get<float>("koef", 100.0f);
inline const float Meters2Pixels(float meters) { return meters * PixelsPerMeter; }
inline const float Pixels2Meters(float pixels) { return pixels / PixelsPerMeter; }
const float ScreenArea = Pixels2Meters(ScreenSizeX) * Pixels2Meters(ScreenSizeY);
It worked before, but now ScreenArea = inf somehow. I use it from static function. I put a breakpoint in that function and print out the value of PixelsPerMeter(100.0), ScreenSizeX and ScreenSizeY. Everything is okay, but ScreenArea is calculated wrong.
When I write directly Pixels2Meters(ScreenSizeX) * Pixels2Meters(ScreenSizeY) instead of using ScreenArea constant everything works.
How it could be?
I think, the problem is with your global variable, to be precise with its initialization.
If by the time the variable has not been dynamically initialized when you call Pixels2Meters(), the variable PixelsPerMeter is statically initialized to zero, so the function Pixels2Meters() returns inf which very much implies PixelsPerMeter is zero.
But you put break points, the story could be slightly different; it is analogous to Heisenberg uncertainty principle, in the sense that when you want to see the value of PixelsPerMeter by putting breakpoints, it shows you different value than the value when there is no breakpoints.
Also note that since the variable is declared const, without extern keyword, the variable has internal linkage, which means you will have different copy of this variable in each translation unit, in case if it declared in a header file which you include in several source files. The variable's behavior is as if it is declared static.
Another important point to be noted is that this variable is initialized twice: the first initialization is called static initialization which happens at compile-time, and second initialization is called dynamic initialization which happens at runtime. In case of static initialization, the variable is initialized to zero, and that is the value which is being used which is causing the problem. To know more about it, read this:
What is dynamic initialization of object in c++?
You should also read about this:
static initialization order fiasco
When the static function is initialised is a bit complicated and may depend on system/compiler.
You probably have an issue that the ConfigManager() isn't initialised before the static function you are using it in.
Related
I recently realized I have the following in my C++ code, and it compiles and runs without any problems.
void MyClass::foo(int a) {
const double x = a;
...
//do stuff with x
...
}
My question: I thought const variables were assigned a value at compile time and this would have given me a compile error, though in this case it obviously is assigned at runtime. Is the const specifier here being ignored? Or is there something else more complicated going on? Should I remove the const specifier?
Constant variables are assigned a value when initialized (at run-time), and cannot be modified afterwards. References and pointers to constant variables can only be used to read from those variables, the underlying variable being constant or not.
I thought const variables were assigned a value at compile time
What you are describing are C++11 constexpr variables.
Should I remove the const specifier?
No. You should make everything const unless you specifically need it to not be const.
generate = !generate;
I saw this in the generateGaussianNoise function here: https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
double generateGaussianNoise(double mu, double sigma)
{
static const double epsilon = std::numeric_limits<double>::min();
static const double two_pi = 2.0*3.14159265358979323846;
thread_local double z1;
thread_local bool generate;
generate = !generate;
I don't understand the logic of this: variable = !variable;
coming from a Python background. Can someone explain?
One specific question: I would expect generate = True to be somewhere here bbut I don't see it.
Two specific question:
if (!generate)
return z1 * sigma + mu;
How can this code work if z1 is not assigned until AFTER this piece of code?
According to this reference
Variables declared at block scope with the specifier ... thread_local (since C++11) have ... thread (since C++11) storage duration but are initialized the first time control passes through their declaration
[Emphasis mine]
So when the function is called the first time, the generate variable will be default initialized which for thread_local variables means zero initialization. Zero initialization for a bool variable means it will be set to false, and for a double it will be 0.0.
It's a quick way to flip a bool variable from true to false and vice versa. It avoids having to write:
if (generate)
generate = false;
else
generate = true;
As for the initialization of generate, thread-local variables get default-initialized. For a bool that means false.
thread_local is type of storage duration; new to C++11. It's the same as static except you get a new instance of the variable per-thread.
Like static, a thread_local bool type is initialised automatically to false.
generate = !generate; flips that value, and that value is retained on a per-thread basis for a subsequent invocation of that function.
I wouldn't recommend generating Guassian random numbers in this manner though - the technique is painfully slow (sampling with rejection is faster). The code in the link you cite is terrible - for starters rand() is not thread safe so all this thread_local stuff is a nonsense. And the use of std::numeric_limits<...>::min() for an "epsilon" shows minimal understanding of floating point properties.
There's no need to program at this low level; C++11 has Box-Muller built in to it's much-improved random number libraries.
generate is acting as a flag variable, which toggles as per need. It is analogous to
if (generate == True)
generate = False
else
generate = True
For the second part of the code, where
How can this code work if z1 is not assigned until AFTER this piece of code?
As it is a return statement, this must be a part of some function or so, and hence z1 must be defined in the calling function and its value passed to the called function.
I spotted a "mistake" in my code today... But I'm not sure if the "mistake" actually changes the resulting compiled code.
Consider initialization of the following reference to a double, x.
double &x{*_data->x_double}; // x_double is a member variable of the struct
// _data, it is a pointer to another double
// eg, I have this somewhere else...
struct data
{
double *x_double;
};
data *_data = new data; // edit: duh, this has to be a pointer...
double another_x = 10.0;
_data->x_double = &another_x; // edit: pointer here too!
However I made the following "mistake"... (notice the extra = sign)
double &x={*_data->x_double};
This code is a minimal example copied from my actual code, in which I don't have references to doubles, but references to large objects such as std::vector's.
The reason for the reference variables is that they are used in an algorithm, and the variable names are very long, so I create shorted aliases for those variables using references. Hope it makes sense why I did that...
So, I've "corrected" the "mistake" but has my output compiled code actually changed?
They're both list initialization. For your cases:
double &x={*_data->x_double};
Is :
6) initialization of a named variable with a braced-init-list after an
equals sign
And
double &x{*_data->x_double};
Is :
1) initialization of a named variable with a braced-init-list (that
is, a possibly empty brace-enclosed list of expressions or nested
braced-init-lists)
Their effects are in this case exactly the same.
Can someone help me to explain this:
I declare a constant in the headerfile:
const int INCRSIZE;
Then in the MIL the constant is initialized:
: INCRSIZE(10)
then later on in a function in the code (its a callback-function used in a gtkmm-GUI
bool MyWindow::on_drawing_expose_event(GdkEventExpose* event)
I allocate an array on the stack using this constant
double arrPxStep[INCRSIZE];
when I compiling i get the following errors:
-expected constant expression
- cannot allocate an array if constant size 0
- arrPxStep unknown size
I know the constant is initialzed - how come the array cannot use this constant memeber-variable that was alreade initialized in the MIL?
By the looks of the code you post, INCRSIZE is a non-static member of a class. You can't use this to initialize an array, even if the value is always set to the same in the constructor. It's just the rules.
Make INCRSIZE a static const member, defined within the class, and it will work.
It is very hard for compiler to detect, that your variable INCRSIZE is const and initialized. So it processes INCRSIZE as usual integer variable. Since you set value to this variable in constructor of your class, compiler should know something about order of calls of your functions (for you it is obvious, that constructor will be the first called function, but for compiler it is not so easy to analyze it). So, it is not included in Standard of C++ (one of reasons: because it is unnecessary and hard to support).
Question 1:
How can you tell the default value of a variable? That is (if my vocabulary is wrong) the value of a variables before it is assigned?
Question 2:
How does this differ between compilers?
Question 3:
Is there a better way to default values?
Question 4:
And finally, are there other exceptions to this rule?
Example code:
bool foolean;
int fintoo;
double fooble;
char charafoo;
What would these be by default compiler to compiler?
In all versions of C++, all the variables in your question will be zero-initialized (statically) if they're declared at namespace scope. In all other cases, they will have garbage values if left uninitialized.
Note that a garbage value is anything which is at the memory location where the variable is defined — it is just a pattern of 0s and 1s. Such values shouldn't be read by your program, else your code will invoke undefined behaviour.
In C++11, if you write these as local variables (or namespace variables):
bool foolean {};
int fintoo {};
double fooble {};
char charafoo {};
They're default-initialized which means zero in this case (as they are built-types).
If a variable is automatic (that is, a non-static variable local to a function, or a member thereof), there is no default. From pratical perspective, the variable is allocated on stack, and what's there on the stack (probably leftover from a previous function call) will become the value of the variable.
Also, some compilers add code to initialize the stack frame to a well-known value in debug mode. That lets you easily see that a variable hasn't been initialized while debugging.
If a variable is static (declared in namespace scope, or with the static keyword in a function), the default is zero.