Skip to main content

Default Initialization

Object created without explicit initializer. Behavior depends on type and storage duration. Dangerous for fundamental types in local scope.

Undefined Values

Local fundamental types (int, double, pointers) = indeterminate values = undefined behavior when read.

Fundamental Types

Automatic Storage (Local Variables)

void function() {
int x; // Indeterminate value ❌
double d; // Indeterminate value ❌
int* ptr; // Indeterminate pointer ❌

std::cout << x; // ❌ UB: reading garbage
std::cout << d; // ❌ UB
*ptr = 42; // ❌ UB: pointer points nowhere
}

Why: Performance - no automatic zeroing. Problem: Forgetting to initialize = bugs.

Static Storage (Globals/Static)

int global;              // Zero-initialized ✅
static int file_static; // Zero-initialized ✅

void function() {
static int local_static; // Zero-initialized ✅

std::cout << global; // ✅ Safe: 0
std::cout << file_static; // ✅ Safe: 0
std::cout << local_static; // ✅ Safe: 0
}

Rule: Static storage = always zero before any other initialization.

Storage Duration Comparison

StorageScopeInitializationLifetime
AutomaticLocalIndeterminate ❌Block scope
StaticGlobal/StaticZero ✅Program lifetime

Class Types

With Default Constructor

class Widget {
int value;
public:
Widget() : value(42) {} // Default constructor
};

Widget w; // Calls Widget() ✅
// w.value guaranteed to be 42

Guarantee: Default constructor always called, object always valid.

Implicit Default Constructor

// ❌ Dangerous
class Point {
int x, y; // No constructor
};

Point p; // x, y indeterminate! ❌

// ✅ Safe
class SafePoint {
int x, y;
public:
SafePoint() : x(0), y(0) {} // Explicit init
};

SafePoint sp; // x=0, y=0 ✅

Lesson: Compiler-generated default constructor doesn't initialize fundamental members.

Deleted Default Constructor

class File {
public:
File() = delete; // Prevent default construction
File(const char* filename) { /* open file */ }
};

// File f; // ❌ Error: default constructor deleted
File f("data.txt"); // ✅ Must provide filename

Use: Force required parameters at construction.

Arrays

void function() {
int arr[10]; // All elements indeterminate ❌
std::cout << arr[0]; // ❌ UB
}

static int global_arr[10]; // All zeros ✅
std::cout << global_arr[0]; // ✅ Safe: 0

Class Type Arrays

class Widget {
public:
Widget() { std::cout << "Constructed\n"; }
};

Widget arr[3]; // Calls Widget() three times ✅
// All elements properly initialized

Member Variables

// ❌ Bad
class Bad {
int value; // Not initialized!
public:
Bad() {} // Constructor doesn't init value

int getValue() { return value; } // ❌ Returns garbage
};

// ✅ Good
class Good {
int value;
public:
Good() : value(0) {} // Initializer list

int getValue() { return value; } // ✅ Returns 0
};

Fix: Always initialize in constructor initializer list.

In-Class Initializers (C++11)

class Widget {
int value = 42; // In-class initializer
std::string name = "default";

public:
Widget() {} // Uses defaults
Widget(int v) : value(v) {} // Overrides value only
};

Best practice: Provide defaults, override when needed.

Quick Decision Tree

Best Practices

DO
  • Always initialize fundamental types explicitly
  • Use in-class initializers (C++11)
  • Initialize in constructor initializer list
  • Use value initialization {} for safety
DON'T
  • Read uninitialized local variables
  • Rely on implicit zero for local variables
  • Assume compiler-generated constructors initialize members
  • Leave member variables uninitialized

Summary

Default Initialization - Key Points

Storage-Dependent Behavior:

  • Automatic (local): Fundamentals = indeterminate (UB if read) ❌
  • Static/global: Always zero-initialized ✅
  • Class with constructor: Calls default constructor
  • Class without constructor: Members stay indeterminate ❌

Critical Rules:

  • Never read uninitialized local variables
  • Compiler-generated constructors don't initialize fundamental members
  • Static storage always zeroed before other initialization

Solutions:

  • Always explicitly initialize fundamentals
  • Use value initialization {} for safety
  • Use in-class initializers (C++11)
  • Initialize members in constructor initializer list
// Interview answer:
// "Default initialization: local fundamentals get indeterminate
// values (UB if read), static/global get zeros. Classes call
// default constructor if available, but compiler-generated ones
// don't initialize fundamental members. Solution: always
// explicitly initialize fundamentals, use value initialization
// {} or in-class initializers, initialize members in constructor."