Ben
Ben

Reputation: 4676

Why is zero-initialization not the default for non-initialized variables in c++? Is there a compiler option to force it?

In most languages I know, scalar-type variables are zero-initialized by default, if they were not initialized in the code. Why doesn't this happen in c/c++? The only reason I could think of is performance, but

Wouldn't it be easier to explicitly tell the compiler somehow not to zero-initialize a variable, if this might be a performance issue?

An finally my question: Is there a gcc option to tell the compiler to zero-init by default?

Upvotes: 6

Views: 3994

Answers (7)

Theodor Badea
Theodor Badea

Reputation: 464

These are from C++ Core Guidelines:

  • ES.20 : Always initialize an object
  • ES.21: Don’t introduce a variable (or constant) before you need to use it
  • ES.22: Don’t declare a variable until you have a value to initialize it with

More can be found here.

As far as I know, global variables will be explicitly 0, but locals will have a different value (in case of a bool variable, this will lead to true).

Visual Studio(just an example), in DEBUG mode, explicitly initializes variables to given values(which can be noticed easily, usually cause an out of bound error or access violation). In RELEASE mode, memory is not explicitly initialized and it just keeps the content that was there before.

Upvotes: 0

metal
metal

Reputation: 6332

The down-side: Potential errors because of uninitialized values.

The up-sides:

  1. Efficiency. You don't pay for it if you don't need it.
  2. The compiler doesn't add assumptions about the right init value. Per @chris in the comments to the OP, you can get a false sense of security since 0 is not always the right initialization value. If it should start as -1, then 0 is wrong.

The mitigations:

  1. Use constructors to initialize your non-POD types
  2. Use "Almost Always Auto" to enforce initialization at declaration time. (Or as @Peter notes in the comments, use explicit types but don't declare a variable until you can properly initialize it. This is implied by AAA, but AAA makes it harder to get wrong since you can't accidentally forget to initialize because the initialization carries the type information also.)
  3. Crank up compiler warnings. For gcc, use -Wall -Werror, which includes -Wuninitialized and then will error on uninitialized values.

The origin: In the hoary old days of C, all declarations came first before initialization. Compare this example from the K&R book:

int main(void)
{
  double sum, atof(char s[]);
  char line[MAXLINE];
  int getline(char line[], int max);

  sum = 0;
  while (getline(line, MAXLINE) > 0)
    printf("\t%g\n", sum += atof(line));
  return 0;
}

C++ retained compatibility with C in this regard, but that came with what is an unfortunate default behavior.

Upvotes: 5

catnip
catnip

Reputation: 25408

I personally would find this useful - as a convenience - if it was optional. Perhaps:

class MyClass
{
    ...
} = 0;

Then, for example, if I add members to my class, I don't have to mess around zero initialising them.

Upvotes: 0

François Andrieux
François Andrieux

Reputation: 29072

One of the founding principals of c++ is to not force developers to pay for what they don't use. If you write something like int x; x = 1; then you shouldn't have to pay for the zero initialization of x, even if that cost happens to be very tiny.

Edit : Regarding your other two points

is it preferable to have undefined behavior?

Undefined behavior is not necessarily a bad thing to have in the language (you can argue both ways). It's definitely a bad thing if you write code that causes it. Notably it gives more freedom to implementers and enables important optimizations.

if I want to avoid undefined behavior, I have to initialize it anyway, so what did I win?

It's not undefined behavior to have an uninitialized variable. It's undefined behavior to try to read from one.

Upvotes: 21

Galik
Galik

Reputation: 48655

The problem with zero initializing variables automatically is that not all your variables should have zero as their initial value. If you forget to initialize a variable with its correct value, the compiler can easily warn you that you used an uninitialized variable.

However if the compiler initialized every variable to zero whether it was your intention or not, then you would never know when you forgot to give them their correct value because the compiler would be unable to tell you.

Example:

std::string some_input = "27";

// ...

int i;
std::istringstream(some_input) >> i; // give i a value 

// ...

std::cout << "stuff: " << i << '\n'; // use i here

Now what if I forget to give i a value?

int i;
// whoopsie I forgot to give i its value 

// ...

std::cout << "stuff: " << i << '\n'; // COMPILER WARNING uninitialized!

Now what happens if the compiler (or I) zero initializes it?

int i = 0;
// whoopsie I forgot to give i its value 

// ...

std::cout << "stuff: " << i << '\n'; // oopsie, output the wrong value, undetectable!

Zero initializing can seem like your friend but, if the variable should not contain zero, making it zero is giving it the wrong value. That is a silent corrupting influence on your data that is hard to spot.

Upvotes: 2

eerorika
eerorika

Reputation: 238461

is it really that performance-consuming, if I do initialize it?

Performing zero initialisation is potentially more performance-comsuming than not performing it, yes.

is it preferable to have undefined behavior?

It is preferable to let the programmer decide whether they want performance (no zero initalisation before assigning the value later) and potential for UB in case of a bug or whether they want deterministic behaviour upon such bug (by explicitly value-initialising even when it is unnecessary).

At least, it was preferred by the people who designed C++ (and C before that). I'm sure it is still preferred by many who choose to use C++, considering there exists languages which don't have UB that could have been chosen instead.

if I want to avoid undefined behavior, I have to initialize it anyway, so what did I win?

Sometimes you don't have the value to which the value should be initialised to until after the object is created. In such case, you can assign the value later. By not initialising to zero, you win not having to set the value more than once.

Upvotes: 0

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 123431

is it really that performance-consuming, if I do initialize it?

Tiny overhead is still overhead, hence yes it is.

is it preferable to have undefined behavior?

If the alternatives are worse performance or declaring something as not valid code then yes it is preferable to declare wrong usage as undefined behaviour.

if I want to avoid undefined behavior, I have to initialize it anyway, so what did I win?

Usually you declare variable only when you use them, but consider this contrived example

int a,x;
if (some_condition) {
    x = foo();
} else {        
    a = foo();
    x = foo(a);
}
return x;

It is a bit contrived (you would probably declare a only when you need it), but if every variable would get initialized, then this code would suffer some overhead for no good reason.

Upvotes: 0

Related Questions