I am programming for a while now and I've started trying to improve my code. Since I really hate creating bazillion of variables that are used only once in long function, is it good practice to shorten variable scope by using brackets?
i.e.
instead writing:
void fcn()
{
int var1;
// some part of fcn
// use of var1;
// rest of fcn
}
write:
void fcn()
{
// some part of fcn
{
int var1;
// use of var100;
}
// rest of fcn
}
Yes it is indeed a good idea to keep the scope of variables as tight as possible.
In your case, unless you are absolutely certain that your code using var1 will only ever be used in fcn (and if my experience is anything to go by, I tend to misjudge that), you could split that code out to a separate function. Your program will scale better that way, and testing will also be simpler. Else, use scope blocks as you currently do.
There are certainly context in which this approach is a good practice.
It is so wide spreaded around 'if/range for/while/case' statements that explicit initializer in those statement were added in C++17 and C++20.
You shouldn't write int var1; anywhere.
Firstly var1 is a terrible name.
Secondly you now have the potential for undefined behaviour, if any code path can read var1 before it is assigned.
Prefer
int meaningfulName = initialValue;
Or even better
const int meaningfulName = value;
Having done that, the scopes you are choosing between are more restricted. If there is still a choice, prefer the narrowest scope possible.
Related
I can think I can vaguely remember seeing a few years ago a way to essentially enter a variable Structure and work on its members without calling the variable name every time. similar to how you can us "using namespace bla". It may have even been from pascal are some left field API that I have used.
e.g
typedef struct time{
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t period;
}time;
void clockFunct(){
static time clock{0,0,0,am};
/*SOME SYNTAX THAT I CANT FIND/REMEMBER*/ clock{
hour = 2;
minute = 30;
second = 20;
period = pm
};
}
I could create some local variables and pass it back but i'm working on micro-controllers so space is a bit of a premium... or just not be lazy and write out the structure name. Just thought I would put it out there and see if anyone knew what I was talking about
Since you did tag C++, you can kind of do what you want in the near future (though the advisability of it is questionable). c++17 sees the introduction of structured bindings to the language:
static time clock{0,0,0,am};
{
auto& [hour, minute, second, period] = clock;
hour = 2;
minute = 30;
second = 20;
period = pm;
};
Inside the block scope, those identifiers will refer (because of the reference qualifier) to the members of clock. And you don't need the block scope at all, actually. I just limited it to simulate the semantics you wanted more closely.
In C99, you can specify a designator in struct initialization
static time clock = { .hour =2, .minute =30, .second = 20, .period =pm };
There's no such syntax, you've probably seen it in other languages. Just write the correct member access operators, the code is normally more readable that way anyways.
That said, with your example code, you can assign the whole struct at once in C (not in C++) using a compound literal:
clock = (time){2, 30, 20, pm};
or, with designated initializers for more clarity (which also helps to avoid bugs):
clock = (time){ .hour=2, .second=30, .minute=20, .period=pm };
The language you're thinking of is C++, not C. And specifically, the behavior you're thinking of is seen in member functions.
We can change the function definition to void time::clockFunct() {. We'd first need to drop the typedef, though. That's actively problematic in C++ as it changes the meaning of time.
Note that it wasn't good C either - C has a function time() in the Standard Library.
While upgrading a legacy project to VS2015, I noticed there were a lot of errors where a local variable was redefined inside a function for example.
void fun()
{
int count = applesCount();
cout << "Apples cost= " << count * 1.25;
for (int bag=0; bag<5;bag++)
{
int count = orangesCount(bag);
cout << "Oranges cost = " << count * 0.75;
}
}
The error/warning message by compiler is:
declaration of 'count' hides previous local declaration
I know it is obviously not a good practice to use the same name for variable count but can the compiler really mess things up as well or generally they deal this situation rather gracefully?
Is it worth it to change and fix the variable names or is unlikely to cause any harm and is low or no risk?
I noticed there were a lot of errors where a local variable was redefined inside a function for example.
You are not demonstrating redefining here. You show an example of variable shadowing.
Variable shadowing is not an error syntactically. It is valid and well defined. However, if your intention was to use the variable from the outer scope, then you could consider it a logical error.
but can the compiler really mess things up
No.
The problem with shadowing is that it can be hard to keep track of for the programmer. It is trivial for the compiler. You can find plenty of questions on this very site, stemming from confusion caused by shadowed variables.
It is not too difficult to grok which expression uses which variable in this small function, but imagine the function being dozens of lines and several nested and sequential blocks. If the function is long enough that you cannot see all the different definitions in different scopes at a glance, you are likely to make a misinterpretation.
declaration of 'count' hides previous local declaration
This is a somewhat useful compiler warning. You haven't run out of names, so why not give a unique name for all local variables in the function? However, there is no need to treat this warning as an error. It is merely a suggestion to improve the readability of your program.
In this particular example, you don't need the count in the outer scope after the inner scope opens, so you might as well reuse one variable for both counts.
Is it worth it to change and fix the variable names
Depends on whether you value more short term workload versus long term. Changing the code to use unique, descriptive local variable names is "extra" work now, but every time someone has to understand the program later, unnecessary shadowing will increase the mental challenge.
IMHO, bad coding practice. Hard to maintain and read.
The compiler can discern between the outer variable and the internal variable.
With a good vocabulary (and a thesaurus), one doesn't need to use the same variable names.
Shadowing a variable (which is what this is) has completely well defined semantics, so the compiler won't mess it up. It will do exactly what it has been told, with well defined result.
The problem is (as is often the case) with the humans. It is very easy to make mistakes when reading and modifying the code. If one is not very careful it can be tricky to keep track of which variable with a given name is being referenced and it's easy to make mistakes where you think you are modifying one but in reality you are modifying another.
So, the compiler is fine, the programmer is the problem.
In my experience, compilers usually handle this issue pretty gracefully.
However, it is definitely bad practice, and unless you have a really compelling reason to do so, you should either reuse the old variable (if it logically makes sense to do so), or declare a [differently-named] new variable.
Can be very bad:
Consider this
std::vector<int> indices(100);
if (true) {
std::vector<int> indices(100);
std::iota(indices.begin(), indices.end(), 0);
}
// Now indices will be an all-0 vector instead of the an arithmetic progression!
In Visual Studio, compiling with Warning Level4 /W4 will output a warning even when disambiguating by prefixing with the implicit this pointer, like in this->Count:
warning C4458: declaration of 'Count' hides class member
Although the compiler rarely makes a mistake with the values, shadowing can be abused and get confusing overtime.
Below is an example of shadowing the Count member variable which should be avoided:
From the Unreal Coding Standard document.
class FSomeClass
{
public:
void Func(const int32 Count)
{
for (int32 Count = 0; Count != 10; ++Count)
{
// Use Count
}
}
private:
int32 Count;
}
One option to dealing with this would adding a prefix to the incoming argument name when shadowing occurs, like so:
class FSomeClass
{
public:
void Func(const int32 InCount)
{
Count = InCount;
for (int32 Counter = 0; Counter != 10; ++Counter)
{
// Use Count
}
}
private:
int32 Count;
}
When using RAII resources it may actually simplify the code to shadow variables and not create new variable names.
An example, a simple logger which writes to stdout when entering and leaving a block:
class LogScope {
private:
std::string functionName;
uint32_t lineNo;
public:
LogScope(std::string _functionName, uint32_t _lineNo) :
functionName(_functionName), lineNo(_lineNo) {
std::cout << "Entering scope in " << functionName << " starting line " << lineNo << std::endl;
};
~LogScope(void) {
std:: cout << "Exiting scope in " << functionName << " starting line " << lineNo << std::endl;
};
};
It could be used like:
void someFunction() { // First scope here.
LogScope logScope(__FUNCTION__, __LINE__);
// some code...
// A new block.
// There is really no need to define a new name for LogScope.
{
LogScope logScope(__FUNCTION__, __LINE__);
// some code...
}
}
Having said that, normally it is good practice, not to reuse your variable names.
Zar,
The compiler will handle this situation fine. In your example, the count variable is defined in two different scopes '{}'. Due to the scope of the variable, the assembly language will refer to two different addresses on the stack. The first 'count' might be the stack point, SP-8, while the inner count might be SP-4. Once transformed into an address the name is irrelevant.
I would not generally change working code for stylistic reasons. If the code is a mess then you run the risk of breaking it. Usually messy code doesn't have any good tests so it hard to know if you broke it.
If you need to enhance the code then certainly tidy up.
--Matt
I'm thinking about a different implementation of this part of a code:
unsigned int whyamIexisting=100000; // also good for me static unsigned ...
double rand_number_generation(){
// create random number [0,1]
static unsigned int rand_counter=0;
rand_counter++;
if( rand_counter > whyamIexisting) {
update_my_seed(time(NULL));
rand_counter=0;
}
// random number generation
return thats_your_gorgeous_numb(); // random algorithm
}
main(){
...modify whyamIexising
...use rand_number_generation() several times
...
}
Should I not use global variable? And if yes what solution will you suggest?
thanks!
If you are working with multiple functions and using a global variable, i would suggest you not to modify it and instead use local variable for storing it and then do the modification.
I usually avoid using global variables. :-)
There... gone!
double rand_number_generation(unsigned int whyamIexisting){
// create random number [0,1]
static unsigned int rand_counter=0;
rand_counter++;
if( rand_counter > whyamIexisting) {
update_my_seed(time(NULL));
rand_counter=0;
}
// random number generation
return thats_your_gorgeous_numb(); // random algorithm
}
main(){
unsigned int limit = 17;
...use rand_number_generation(limit) several times
...
}
There is no point having a global variable in your case. It only makes the program hard to maintain if it were to grow. It doesn't add anything in the example you have given.
I don't know the rest of code, so it's based on fragments you posted and may be completely wrong.
whyamIexisting is kind of a description for environment where rand_number_generation is run, but it also describes it's state, same as rand_counter.
From tags I see that you write in C++, which is an object oriented language. The thing about object orientation is that you have, you know, objects. Probably not everyone will agree with me (thinking about my High School IT teacher), but I personally consider putting everything that has it's own state into class as a good practise. Does object containing whyamIexisting as it's field, rand_counter as another and rand_number_generation as it's method (and probably getter and setter for whyamIexisting) solve your problem?
Unless you don't use whyamIexisting anywhere else in the code, because then you can simply make it local in main and pass as parameter to function rand_number_generation.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to optimize my code. I've heard that it's better not to use local variables and to reduce the number of function parameters, so currently the structure of my program looks like this:
using namespace std;
const string UPLOAD_LOCATION = "/uploads";
const int value = 100;
const int type = 0;
const int max_value = 255;
string var1, var2, var3;
void func1();
void func2();
void func4();
int main(int argc, char *argv[])
{
func1();
func2();
}
void func1()
{
//do something
}
void func2()
{
func4();
//do something
}
void func4()
{
//do something
}
Would it be more efficient if var1, var2 and var3 were local variables in main function, so I'd pass them as arguments to the functions? I mean something like this:
using namespace std;
const string UPLOAD_LOCATION = "/uploads";
void func1();
void func2();
void func4();
int main(int argc, char *argv[])
{
const int value = 100;
const int type = 0;
const int max_value = 255;
string var1, var2, var3;
var1 = func1(var2, value, type, max_value);
var3 = func2(var2);
}
string func1(string &var2)
{
//do something
}
void func2(string &var2)
{
func4(var2);
//do something
}
void func4(string &var2)
{
//do something
}
If yes, is it better to pass them by reference or by value? For example lets say the function stores the result in string s, then which choice should I make:
a) void func( string in, string &result )
or
b) string func( string in )
Do not make all your locals and parameters globals
No...just...stop.
Make your code understandable to yourself and other human beings. That should be your goal. That's what you can do that a computer cannot.
Let your compiler optimize things. That's what it can do way better than you. If things will run much faster with certain variables not put on the stack, your compiler should be quite capable of recognizing that.
If you want more specific design goals when creating classes and methods, try to minimize coupling and maximize cohesion. Often times, you will even find that you get efficiency for free when you do this.
If the result isn't fast enough to meet requirements, with your compiler's optimization settings full out, only then should you really concern yourself with hand-optimizing. In this case, you get a profiler and actually measure what parts of your code are wasting the most time, and fix those parts. That way you don't stumble around punching at nothing like a blind boxer.
I'll take a stab at a couple of the questions
In the past it has always been better to pass by reference then value if you are not worried about the method you are calling modifying the value. IF you pass by value it has to do a copy construct, if you pass by reference it's just passing a pointer.
That said, C++ 11 is smarter and more efficient with the pass by value. So this is no longer a hard and fast rule. See this article for more info.
IN reference to your last question about having your value returned in as a parameter or the output of the method. This article is good at pointing out the pros and cons
Premature optimization is root of all evil
First and foremost make your program readable. Then make it work and only then and only if necessary optimize it. First optimize it on algorithm level, then run through profiler, find where your program spends most of the time and optimize that.
To your question:
void func( string in, string &result );
void func( string in );
Let's look which way is more readable to call such a function:
string str;
func( "foobar", str );
vs:
string str = func( "foobar" );
Can you guess at least in which case it is easier to understand that str is modified after func() call? As for optimization C++ committee did a great job to make more natural way of passing and returning values to/from functions as efficient as their less readable equivalent. So stop worry about what does not really matter and focus on what is necessary to write a good program.
I'm trying to optimize my code. I've heard that it's better not to use local variables and to reduce the number of function parameters
It is better to not use global state (variables and objects) and to reduce number of function parameters (where this makes sense). Your confusion here seems to come from the idea that this "it's better" means "it's better for efficiency reasons".
You will not optimize the speed (or memory footprint) of your code by reducing global state and number of function parameters. Instead, you will compartimentalize functionality and reduce interependency of various modules in your application making it easier to read, maintain and extend.
Would it be more efficient if var1, var2 and var3 were local variables in main function, so I'd pass them as arguments to the functions?
No. This has nothing to do with efficiency (but your second example of the same code is much easier to read).
I was wondering if there was a simple way to write an alias of a c++ class function. For instance, if I have some list container object, a logical function would be
int list::length() { return len; }
But another logical alias that programmers might use could be
int list::size() { return len; }
So, instead of writing both functions with their full body, is there any way to make list::size() an alias of list::length() such that it isn't a duplicate when compiled, but rather references the same function?
I've read that you can do this with #define, but I don't want to cause any confusion with other code-names somewhere totally out of scope (i.e. a 'size' variable).
I've also read that function pointers can fix it, but that isn't exactly an alias (since it has to apply de-referencing), nor can function pointers be given a declaration, giving it a confusing help-line to users (I would think), plus the confusion if ever I need to nest my code inside another object (I have to adjust the scope).
One of my guesses is, will the following be taken as a direct function alias by most optimizing compilers:
inline int list::length() { return len; }
inline int list::size() { return length(); }
Or, is there any strict 'alias' syntax for c++? (I couldn't find any - wasn't sure)
So then, what would be the most efficient way of doing this?
EDIT: I've accepted the answer simply to wrap up the question, since it's only a curiosity of mine. Anyone with good information, please add comments or answer, and I may even change my answer.
I would not use the preprocessor and #define to do this. In general preprocessor should be a last resort in C++. See this C++ FAQ on inline functions which also contains a section on the various evils of using macros of the preprocessor.
The approach I would use would be to have a function that will have several different aliases with a more complicated function and interface you would do something like the following:
int list::length(string xString, int iValue) {
int iReturnValue = 0; // init the return value
// do stuff with xString and iValue and other things
return iReturnValue;
}
Then do something like the following for an alias.
inline int list::size(string xString, int iValue) {return length(xString, iValue);}
The inline should basically just replace the alias with the actual function call.
See also this stack overflow posting Giving a function implementation more than one name. It provides some reasons why you might not want to do this.