C++ Default Initialization | A Guide to "Default Initialization"
이 글의 핵심
Default initialization in C++: when scalars are indeterminate, static zero-init, and avoiding UB with value initialization.
What is Default Initialization?
When a variable is declared without an initializer, default initialization is applied. For local variables, this can result in garbage values. If you need safe zero/default values, use value initialization or zero initialization. To avoid undefined behavior, it’s a good practice to ensure variables are properly initialized before use.
int x; // Default initialization (garbage value)
int y = 10; // Explicit initialization
Primitive Types
void func() {
int x; // Garbage value
double d; // Garbage value
int* ptr; // Garbage value
// Must initialize before use
x = 10;
d = 3.14;
ptr = nullptr;
}
Practical Examples
Example 1: Local Variables
void func() {
int x; // Garbage value
// ❌ Using before initialization
std::cout << x << std::endl; // Undefined behavior
// ✅ Using after initialization
x = 10;
std::cout << x << std::endl; // OK
}
Example 2: Classes
class Widget {
int value; // Default initialization
public:
Widget() {} // `value` is a garbage value
};
// ✅ Member initialization
class Widget {
int value;
public:
Widget() : value(0) {} // Explicit initialization
};
Example 3: Arrays
void func() {
int arr[5]; // Garbage values
// ❌ Using before initialization
for (int x : arr) {
std::cout << x << " "; // Undefined behavior
}
// ✅ Initialize before use
for (int& x : arr) {
x = 0;
}
}
Example 4: Global vs Local Variables
int global; // 0 (global variable)
int main() {
int local; // Garbage value (local variable)
std::cout << global << std::endl; // 0
// std::cout << local << std::endl; // Undefined behavior
}
Undefined Behavior
void func() {
int x;
// ❌ Undefined behavior
if (x > 0) {}
int y = x + 10;
int* ptr = &x;
std::cout << x;
}
Common Issues
Issue 1: Missing Initialization
// ❌ Not initialized
int sum;
for (int i = 0; i < 10; i++) {
sum += i; // Undefined behavior
}
// ✅ Proper initialization
int sum = 0;
for (int i = 0; i < 10; i++) {
sum += i;
}
Issue 2: Pointers
// ❌ Not initialized
int* ptr;
if (ptr) {} // Undefined behavior
// ✅ Initialize to nullptr
int* ptr = nullptr;
if (ptr) {} // OK
Issue 3: Class Members
// ❌ Not initialized
class Bad {
int value;
public:
Bad() {} // `value` is a garbage value
int getValue() { return value; } // Risky
};
// ✅ Proper initialization
class Good {
int value = 0; // Member initialization
public:
Good() = default;
};
Issue 4: Conditional Statements
int x;
// ❌ Using before initialization
if (condition) {
x = 10;
}
std::cout << x; // Garbage value if condition is false
// ✅ Proper initialization
int x = 0;
if (condition) {
x = 10;
}
Best Practices for Initialization
// ✅ Always initialize
int x = 0;
int y{};
int* ptr = nullptr;
// ✅ Member initialization
class MyClass {
int value = 0;
double data = 0.0;
};
// ✅ Array initialization
int arr[5]{};
Practical Examples
Example 1: Accumulator Bug
// ❌ Common bug: uninitialized accumulator
int calculate_sum(const std::vector<int>& numbers) {
int sum; // Garbage value!
for (int n : numbers) {
sum += n; // UB: sum is uninitialized
}
return sum;
}
// ✅ Correct: initialize accumulator
int calculate_sum(const std::vector<int>& numbers) {
int sum = 0; // Initialized
for (int n : numbers) {
sum += n; // OK
}
return sum;
}
Example 2: Configuration Class
// ❌ Uninitialized members
class Config {
int port;
bool enabled;
std::string host;
public:
Config() {} // port and enabled are garbage!
};
// ✅ Initialize all members
class Config {
int port = 8080;
bool enabled = false;
std::string host = "localhost";
public:
Config() = default; // All members initialized
};
// ✅ Alternative: Constructor initialization
class Config {
int port;
bool enabled;
std::string host;
public:
Config() : port(8080), enabled(false), host("localhost") {}
};
Example 3: Buffer Initialization
// ❌ Uninitialized buffer (security risk)
void process_data() {
char buffer[1024]; // Garbage values
// If not fully written, may leak old memory contents
send_to_network(buffer, sizeof(buffer)); // Security risk!
}
// ✅ Zero-initialize buffer
void process_data() {
char buffer[1024]{}; // All zeros
// Safe even if not fully written
send_to_network(buffer, sizeof(buffer));
}
Example 4: Optional Values
// ❌ Using sentinel value with uninitialized variable
int find_max(const std::vector<int>& numbers) {
int max; // Garbage!
bool found = false;
for (int n : numbers) {
if (!found || n > max) {
max = n;
found = true;
}
}
return max; // What if numbers is empty?
}
// ✅ Use std::optional
std::optional<int> find_max(const std::vector<int>& numbers) {
if (numbers.empty()) return std::nullopt;
int max = numbers[0];
for (int n : numbers) {
if (n > max) max = n;
}
return max;
}
Debugging Tips
Tip 1: Use Compiler Warnings
# Enable uninitialized variable warnings
g++ -Wall -Wextra -Wuninitialized -Werror main.cpp
# Clang
clang++ -Weverything -Werror main.cpp
Example warning:
warning: variable 'x' is uninitialized when used here [-Wuninitialized]
std::cout << x;
^
Tip 2: Use Static Analysis Tools
# Clang-Tidy
clang-tidy main.cpp -- -std=c++20
# Cppcheck
cppcheck --enable=all main.cpp
Tip 3: Use Sanitizers
# Memory Sanitizer (detects uninitialized reads)
clang++ -fsanitize=memory -fno-omit-frame-pointer main.cpp
./a.out
# Output:
# ==12345==WARNING: MemorySanitizer: use-of-uninitialized-value
Tip 4: Initialize in Debug Builds
#ifdef DEBUG
int x = 0xDEADBEEF; // Obvious garbage value for debugging
#else
int x; // Release build
#endif
Tip 5: Use Valgrind
# Detect uninitialized values
valgrind --track-origins=yes ./a.out
# Output:
# Conditional jump or move depends on uninitialised value(s)
FAQ
Q1: What is default initialization?
A: It occurs when no initializer is provided. This can result in garbage values.
Q2: Why is it dangerous?
A: It can lead to undefined behavior. Always initialize variables.
Q3: What about global variables?
A: They are zero-initialized by default.
Q4: What about classes?
A: The default constructor is called, but members are default-initialized.
Q5: How can I prevent issues?
A:
- Initialize variables at the time of declaration
- Use member initialization
- Initialize in constructors
- Enable compiler warnings (
-Wall -Wextra -Wuninitialized) - Use static analysis tools (clang-tidy, cppcheck)
- Use sanitizers in debug builds
Q6: What’s the difference between default and value initialization?
A:
- Default initialization:
int x;→ garbage value - Value initialization:
int x{};orint x = int();→ zero
Q7: Are class members always default-initialized?
A: Yes, but the result depends on the type:
- Primitive types: Garbage values (unless explicitly initialized)
- Class types: Default constructor is called
- Arrays: Each element is default-initialized
Q8: How do I detect uninitialized variables?
A: Use:
- Compiler warnings:
-Wuninitialized - Static analysis: clang-tidy, cppcheck
- Runtime tools: Valgrind, MemorySanitizer
- Code review: Look for variables declared without
=or{}
Q9: Is it safe to use default initialization for performance?
A: Only if you immediately assign a value before any use. Otherwise, always initialize. The performance difference is negligible, and safety is more important.
// ✅ Safe: immediate assignment
int x;
x = compute_value(); // OK
// ❌ Risky: conditional assignment
int y;
if (condition) y = 10;
use(y); // UB if condition is false
Q10: Where can I learn more about default initialization?
A:
- “C++ Primer” by Lippman, Lajoie, Moo
- “Effective C++” by Scott Meyers
- cppreference.com - Default initialization
Related Posts: Value Initialization, Zero Initialization, Aggregate Initialization, Undefined Behavior.
One-line summary: Default initialization can leave variables with garbage values; always initialize variables explicitly to avoid undefined behavior.
## 같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- [C++ Value Initialization | "값 초기화" 가이드](/blog/cpp-value-initialization/)
- [C++ Zero Initialization | "0 초기화" 가이드](/blog/cpp-zero-initialization/)
- [C++ Aggregate Initialization | "집합체 초기화" 가이드](/blog/cpp-aggregate-initialization/)
- [C++ Undefined Behavior | "미정의 동작" 완벽 가이드](/blog/cpp-undefined-behavior/)
---
---
## 이 글에서 다루는 키워드 (관련 검색어)
C++, default-initialization, initialization, undefined, behavior 등으로 검색하시면 이 글이 도움이 됩니다.