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.
Related
When do I need to initialize variables in c++? Some people assert that its important but maybe this is more an issue in c-language?
I am refferering to primitives i.e. char, int, long, double
Let say I have the following code-snippet
int len;
double sum, mean;
char ch;
while (true) {
// here I use these primitives where they are initialized.
}
So - should I initialized these primitives as a good programming pratice here?
In c++ compiler usualy do not initialize local (automatic) variables. These variables are created on the stack and they are filled with random values. Usualy you do not need to inicialize variables but read carefuly what the compiler says. Try:
int main() {
int x;
x=x+1;
}
and compile it with -Wall switch (I'm using gcc). When the message
x.cpp: In function ‘int main()’:
x.cpp:3:6: warning: ‘x’ is used uninitialized in this function [-Wuninitialized]
x=x+1;
is written, then it would be better to initialize such variable.
The problem is, of course, the use of unitialised variables as in
int x;
int y=1+x; // oops what is y?
AFAIK, the language standard allows the compiler to initialise x to 0, but also to leave it unitialised. In any case, most optimisations (-O) will omit an initialisation in the above situation.
If you use full warning compiler flags (e.g. -Wall -Wextra -pedantic) the compiler will almost certainly spot the usage of unitialised variables (it will also warn about usage of unitialised variables in library header files, such as boost headers -- the boost developers appear to not use such useful diagnostics).
In general, whether or not to initialise all variables is a matter of style. I would provide an explicit initialisation whenever there is a sensible initial value for a variable and/or if there is the danger of it being used unitialised. Different from C, the possibility of unitialised variables is quite rare in C++, in particular when passing by return value (including move semantics).
You should initalize all variables to prevent: "trash in input - trash in output".
When do I need to initialize variables in c++?
You should initialize local variables with a sensible value when you define them. If you cannot give a variable a sensible value yet, then you should probably define it later.
The goal here is to minimize the amount of state in your functions in order to make them easier to understand. When all variables are defined at the beginning of the function, you don't know what they are used for. When they are defined at the point they are needed, it's clear that they are not used before that point. This also helps to limit the scope in which variables are declared (e.g. inside the loop instead of before it, thus less state outside the loop) and it allows you to define more variables as const (thus not adding state).
__declspec(naked) void printfive() {
int i = 5;
printf("%i\n", i);
}
for some reason this code works, but I do not understand where the i is stored? In the frame of the calling function? It becomes global variable? If it is stored in the caller's frame, then how compiler knows the displacement, because you can call printfive() from different functions with different frame size and local variables. If it is global, or something like static maybe, I have tried to go recursive and I can see that variable is not changed, it is not truly local indeed. But that's obvious, there is no entry code (prolog). Ok, I understand, no prolog, no frame, no register change, but this is values, but what happens to the scope? Is the behaviour of this specifier defined in any reference? Is this part of C++ standard anyway? This sort of functions are great if you mostly use asm {} inside them, (or use asm to call them and want to be sure the function is not over optimized), but you can mix with C++. But this is sort of brain twister.
I know this topic is more than several years old, Here are my own answers.
Since no references are made to Microsoft documentation regarding this topic, for those who care to learn more about what is needed or not as stated by Keltar, here is the Microsoft documentation that explains most of what Keltar didn't explain here.
According to Microsoft documentation, and should be avoided.
The following rules and limitations apply to naked functions:
The return statement is not permitted.
Structured Exception Handling and C++ Exception Handling constructs are not permitted because they must unwind across the stack frame.
For the same reason, any form of setjmp is prohibited
Use of the _alloca function is prohibited.
To ensure that no initialization code for local variables appears before the prolog sequence, initialized local variables are not
permitted at function scope. In particular, the declaration of C++
objects are not permitted at function scope. There may, however, be
initialized data in a nested scope.
Frame pointer optimization (the /Oy compiler option) is not recommended, but it is automatically suppressed for a naked function.
You cannot declare C++ class objects at the function lexical scope. You can, however, declare objects in a nested block.
From gcc manual:
Use this attribute ... to indicate that the specified function does
not need prologue/epilogue sequences generated by the compiler. It is
up to the programmer to provide these sequences. The only statements
that can be safely included in naked functions are asm statements that
do not have operands. All other statements, including declarations of
local variables, if statements, and so forth, should be avoided. Naked
functions should be used to implement the body of an assembly
function, while allowing the compiler to construct the requisite
function declaration for the assembler.
And it isn't standard (as well as any __declspec or __attribute__)
When entering or exiting a function, the compiler adds code to help with the passing or parameters. When a function is declared naked, non of the parameter variables assignment code is generated, if you want to get at any of the parameters, you will need to directly access the relevant registers or stack (depending on the ABI defined calling convention).
In your case, you are not passing parameters to the function, therefore your code works even though the function is declared naked. Take a look at the dis-assembler if you want to see the difference.
Recently I had lots of trouble with a non initialized variable.
In Java, the default value of variable is null, therefore an exception is likely to be thrown when if the non-initialized variable is used. If I understood, in C++, the variable is initialized with whatever data turns out to be in the memory. Which means that the program is likely to run, and it might be hard to even know there is something wrong with it.
What would be the clean way to deal with this ? Is there some good programming habit that would reduce the risk ? In my case, the variable was declared in the header file and should have been initialized in the cpp file, which is an example of things that makes error more likely.
thx
Edition after receiving few answers:
My apologies, my question was not specific enough.
The answer I get to use flag for the compilers to get informed of non-initialized variables will be useful.
But there are rare cased variables can not be initialized at the beginning, because depending on the behavior of your system.
in header file
double learnedValue;
in cpp file
/* code that has nothing to do with learnedValue
...
*/
learnedValue = a*b*c; // values of a, b and c computed in the code above
/*code making use of learned value
...
*/
Now what happened is that forgot the line "learnedValue=a*b*c".
But the program was working good, just with value of learnedValue initialized with whatever what was in the memory when it was declared.
In Java, such error is not an issue, because the code making use of learned value is likely to crash or throw an exception (at least you get to know what was wrong).
In C++, you can apparently be happy and never get to know there is a problem at all. Or ?
Pls make sure you have appropriate warning levels set while compiling your program.
Compilers issue appropriate warning whenever un-initialized variables are used.
On g++, -Wall compiler option would show all warnings.
On Visual studio, you might have to use warning level 4.
Also, there are some static code analysis tool available in the market.
cppCheck is one such tool available for free.
You should not define a variable in a header (only declare it). Otherwise you will get other errors when you include the header in several .cpp files.
When actually defining a variable, you can also give it an initial value (like 0). In C++ it is also common to defer the definition of (local) variables until you have a value to assign to them.
In the header file
extern double learnedValue;
^^^^^^
In the cpp file
double learnedValue = 0;
/* code that has nothing to do with learnedValue
...
*/
learnedValue = a*b*c; // values of a, b and c computed in the code above
/*code making use of learned value
...
*/
you can define the variables on the spot they are declared
c++11 allows you to initialize variables inside class. If that is not implemented by the compiler yet then the constructor initialization list is the area to check.
The C# can initialize the variable. But C++ not, so when use a pointer without initialized, it always throw exception. You should make a good habit to initialize all the variables in the class constructor.
The MSDN documentation for the Microsoft-specific __if_exists statement says the following (emphasis added):
Apply the __if_exists statement to identifiers both inside or outside a class. Do not apply the __if_exists statement to local variables.
Unfortunately there is no explanation for why you should not apply this to local variables. It compiles fine and has the expected effect, so I'm wondering if anyone knows why they say not to do this. Is it a correctness issue, or a maintainability issue, or something else?
I realize that this is a Microsoft-specific feature and not portable, but let's assume for argument's sake that there's a good reason to use it.
EDIT: Some folks are curious why I'm doing this, so here's an explanation. I realize this is a dirty hack, so unless you have a good suggestion for a better way to do it, please don't bother pointing out that it's gross. It's the least-gross alternative we were able to find given the large size of the code base.
We have a large body of legacy code (millions of lines) that uses the Microsoft-specific __FUNCTION__ macro as part of an error logging package. A significant fraction of that code is now wrapped inside lambda functions so that we can catch structured exceptions (with __try/__except) and still use unwindable objects. Inside those lambda functions, __FUNCTION__ evaluates to something useless like `anonymous-namespace'::<lambda23>::operator(), which is not useful for anything. Our workaround for this is to define new __FUNCTION__-like macro which checks for the existence of an alternate local variable with the enclosing function name, using __if_exists. Due to how the macros work, we can easily switch to the new __FUNCTION__ substitute and easily define the alternate name variable without changing tons of code, so it's a reasonably clean solution given the limitations. That is, of course, assuming that it's valid to use __if_exists this way.
As I said above, I know it's a dirty hack, so please don't tell me how ugly it is unless you have good ideas on how to do it better.
I don't know for sure, but one guess is a local variable might be optimized away by compiler, and maybe not of course, which renders __if_exists test unrelieable.
And I also don't see the reason to do this for a local variable, you are in that specific scope, you know everything, why you want to test if a local variable exist?
__if_exists is a dirty old hack inside Visual C++, with severe implementation limitations as it was only intended for ATL.
Local variables are special because you can have two local variables with the same name:
void foo()
{
int i = 1;
{
int i = 2;
}
}
This means there's a more complicated datastructure inside the compiler to track them. __if_exists has to do a name lookup, which may not be correct for some types of nested scopes like this.
Another historical case is that in Visual C++, for wasn't correctly scoped:
void foo()
{
for (int i = 1; false; ) { }
__if_exists(i) // What do you expect? VC++ let i escape.
}
You can't have code outside of functions except for declarations, definitions and preprocessor directives.
Is that statement accurate, or is there something I'm missing? I'm teaching my nephew to program, and he was trying to put a while loop before main. He's pretty young, I want to give him a hard simple rule that he can understand.
Not quite -- you can also put expressions in global variable declarations:
int myGlobalVar = 3 + SomeFunction(4) - anotherGlobalVar;
But you can only put expressions here, which have to evaluate to the value you're initializing the global with. You cannot put full statements (no blocks of code, no if statements, no loops, etc.). This code will get executed before main() gets a chance to run, so be careful with what you do here. I'd recommend against calling functions in global initializers unless you can't avoid it.
For your nephew:
no, you can't do it.
For yourself:
The compiler's input is technically what you get after the preprocessor is run. So, let's leave preprocessor out. After it has worked, you get a C++ program which is a sequence of declarations. Some delcarations may also be definitions, and some definitions (like function definitions) may have statements inside them.
HTH
Yes- you can't stick random executable code outside functions.
Yes, every kind of statement that does something must reside inside a context that can use it (this doesn't apply to variable initialization).
This because C++ is a structured programming language that encloses its behaviour inside procedures, as opposed to unstructured ones in which you have just one level of code and no scopes.
Well, there's namespaces...and the stuff Adam Rosenfield mentioned...and there's also exception try/catch that can be sort of external to functions. Unfortunately, I can't remember the syntax and can't find it with google.