views:

219

answers:

8

In many languages you're allowed to declare a variable and use it before initializing it.

For example, in C++, you can write a snippet such as:

int x;
cout << x;

This would of course return unpredictable (well, unless you knew how your program was mapping out memory) results, but my question is, why is this behavior allowed by compilers?

Is there some application for or efficiency that results from allowing the use of uninitialized memory?

edit: It occurred to me that leaving initialization up to the user would minimize writes for memory mediums that have limited lifespans (write-cycles). Just a specific example under the aforementioned heading of 'performance'. Thanks.

+1  A: 

Perhaps in some cases, it is faster to leave the memory uninitialised until it is needed (for example, if you return from a function before using a variable). I typically initialise everything anyway, I doubt it makes any real different in performance. The compiler will have its own way of optimising away useless initialisations, I'm sure.

dreamlax
+4  A: 

The oldest excuse in programming : it improves performance!

edit: read your comments and I agree - years ago the focus on performance was on the number of CPU cycles. My first C compiler was traditional C (the one prior to ANSI C) and it allowed all sorts of abominations to compile. In these modern times performance is about the number of customer complaints. As I tell new graduates we hire - 'I don't care how quickly the program gives a wrong answer'. Use all the tools of modern compilers and development, write less bugs and everyone can go home on time.

james
Wouldn't it improve performance more by not even declaring it? That way, memory wouldn't even need to be allocated for the variable. Anyone who cites performance for this type of code is just plain wrong.
Thomas Owens
The key word being *oldest*. 40 years ago when C was being developed, "wasting" an instruction or two to auto-initialize a variable might have actually mattered.
dan04
Wasting an instruction might have been valuable, but in the sense of performance, having that extra instruction (or two or three) would make the application less performant.
Thomas Owens
C++ programs are not just for powerful desktops. They are also used in small micro-controllers (well C is) and the people who program micron-controllers do not want to give up the extra instructions (it's not just time but space) And why should they; they know the associated problems with using uninitialized memory so why should they pay for the cost (of initialization) when they don't need too. Do we want to enforce the cost on everybody just so that a few inexperienced programmers are protected? I would say they are already protected; modern compilers will always warn you about this problem.
Martin York
+1  A: 

Some languages have default values for some variable types. That being said I doubt there are performance benefits in any language to not explicitly initializing them. However the downsides are:

  • The possibility that it must be initialized and without being done you risk a crash
  • Unanticipated values
  • Lack of clarity and purpose for other programmers

My suggestion is always initialize your variables and the consistency will pay for itself.

N8g
+4  A: 

Some API's are designed to return data via variables passed in, e.g:

bool ok;
int x = convert_to_int(some_string, &ok);

It may set the value of 'ok' inside the function, so initializing it is a waste.

(I'm not advocating this style of API.)

sje397
For "real-world" usage of this, see Qt's QString class: http://doc.qt.nokia.com/4.6/qstring.html#toInt as an example. Notice the bool* ok.
ShaChris23
it depend on the function parameter whether they are OUT-typed, or INOUT-typed.
YeenFei
Same with std input streams: `bool ok; std::cin >> ok; `
rafak
+13  A: 

My thoughts (and I've been wrong before, just ask my wife) are that it's simply a holdover from earlier incarnations of the language.

Early versions of C did not allow you to declare variables anywhere you wanted in a function, they had to be at the top (or maybe at the start of a block, it's hard to remember off the top of my head since I rarely do that nowadays).

In addition, you have the understandable desire to set a variable only when you know what it should be. There's no point in initialising a variable to something if the next thing you're going to do with it is simply overwrite that value (that's where the performance people are coming from here).

That's why it's necessary to allow uninitialised variables though you still shouldn't use them before you initialise them, and the good compilers have warnings to let you know about it.

In C++ (and later incarnations of C) where you can create your variable anywhere in a function, you really should create it and initialise it at the same time. But that wasn't possible early on. You had to use something like:

int fn(void) {
    int x, y;
    /* Do some stuff to set y */
    x = y + 2;
    /* Do some more stuff */
}

Nowadays, I'd opt for:

int fn(void) {
    int y;
    /* Do some stuff to set y */
    int x = y + 2;
    /* Do some more stuff */
}
paxdiablo
+1 Coming from being a C/C++ for many years I ditto this. Was typing a reply along this line too, you beat me to it :) It is wise to initialise a variable with meaningful value as close to your main code logic that uses it as possible - distance metrics.
Fadrian Sudaman
@ozmo, this should be the accepted answer.
ShaChris23
+1 for modern compilers will warn you. Just stick the warning level at the highest level and then make all warnings errors and you have the same effect as forcing people to initialize before use. Just because humans are lazy doe's not mean we cant compensate with smart compilers :-) Long live or compiler overlords.
Martin York
@paxdiablo: Actually, I would probably create an alternate function so that I could write `int y = alternate()` and not have an unitialized `y` either. If only we could have Python like declaration: `if test: y = 3; else: y = 4` goes a long way to prevent uninitialized variables without having to create one-lined functions everywhere.
Matthieu M.
+2  A: 

The short answer is that for more complicated cases, the compiler may not be able to determine whether a variable is used before initialization or not.

eg.

int x;
if (external_function() == 2) {
   x = 42;
} else if (another_function() == 3) {
   x = 49;
}
yet_another_function( &x );
cout << x;   // Is this a use-before-definition?

Good compilers will give a warning message if they can spot a probable use-before-initialize error, but for complex cases - especially involving multiple compilation units - there's no way for the compiler to tell.

As to whether a language should allow the concept of uninitialized variables, that is another matter. C# is slightly unusual in defining every variable as being initialized with a default value. Most languages (C++/C/BCPL/FORTRAN/Assembler/...) leave it up to the programmer as to whether initialization is appropriate. Good compilers can sometimes spot unnecessary initializations and eliminate them, but this isn't a given. Compilers for more obscure hardware tend to have less effort put into optimization (which is the hard part of compiler writing) so languages targeting such hardware tend not to require unnecessary code generation.

MZB
A: 

Depending on the size of the variable, leaving the value uninitialized in the name of performance might be regarded as micro-optimization. Relatively few programs (when compared to the broad array of software types out there) would be negatively affected by the extra two-or-three cycles necessary to load a double; however, supposing the variable were quite large, delaying initialization until it is abundantly clear initialization is required is probably a good idea.

kbrimington
A: 

for loop style

int i;
for(i=0;i<something;++i){
    .......
}
do something with i

and you would prefer the for loop to look like for(init;condition;inc)

here's one with an absolute necessity

bool b;
do{
    ....
    b = g();
    ....
}while(!b);

horizontal screen real estate with long nested names

longer lived scoping for debugging visibility

very occasionally performance

nbourbaki