[2026] C++ Object Lifetime: Storage Duration, RAII, and Dangling
이 글의 핵심
C++ lifetime and storage duration: automatic, static, dynamic, thread_local; destruction order; temporaries; smart pointers and RAII.
What is lifetime?
The period from when an object’s lifetime begins (after construction completes) until it ends (destruction). 다음은 간단한 cpp 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
void func() {
int x = 10; // x begins
// x is usable here
} // x ends
Storage duration
다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 1. Automatic
void func() {
int x = 10; // destroyed at end of block
}
// 2. Static
int global = 10; // program end
void func() {
static int count = 0; // program end
}
// 3. Dynamic
void func() {
int* ptr = new int(10); // until delete
delete ptr;
}
// 4. Thread
thread_local int x = 10; // thread end
Practical examples
Example 1: Automatic storage
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
class Widget {
public:
Widget(int id) : id(id) {
std::cout << "Widget " << id << " ctor" << std::endl;
}
~Widget() {
std::cout << "Widget " << id << " dtor" << std::endl;
}
private:
int id;
};
void func() {
Widget w1(1);
if (true) {
Widget w2(2);
// w2 lifetime: this block
} // w2 destroyed
Widget w3(3);
} // w3, w1 destroyed (reverse order)
int main() {
func();
}
Example 2: Static storage
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
class Logger {
public:
Logger() {
std::cout << "Logger init" << std::endl;
}
~Logger() {
std::cout << "Logger shutdown" << std::endl;
}
void log(const std::string& msg) {
std::cout << "[LOG] " << msg << std::endl;
}
};
Logger globalLogger;
void func() {
static Logger localLogger;
localLogger.log("func");
}
int main() {
globalLogger.log("start");
func();
func();
globalLogger.log("end");
}
Example 3: Dynamic storage
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <memory>
class Resource {
public:
Resource(int size) : size(size) {
data = new int[size];
std::cout << "Resource alloc " << size << std::endl;
}
~Resource() {
delete[] data;
std::cout << "Resource free " << size << std::endl;
}
private:
int* data;
int size;
};
void manualManagement() {
Resource* res = new Resource(100);
delete res;
}
void smartPointer() {
auto res = std::make_unique<Resource>(100);
}
int main() {
manualManagement();
smartPointer();
}
Example 4: Lifetime extension
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
class Temp {
public:
Temp(int val) : value(val) {
std::cout << "Temp ctor: " << value << std::endl;
}
~Temp() {
std::cout << "Temp dtor: " << value << std::endl;
}
int getValue() const {
return value;
}
private:
int value;
};
Temp createTemp(int val) {
return Temp(val);
}
int main() {
const Temp& ref = createTemp(10);
std::cout << "value: " << ref.getValue() << std::endl;
// destroyed when ref goes out of scope
}
Construction / destruction order
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <iostream>
class A {
public:
A(int id) : id(id) {
std::cout << "A" << id << " ctor" << std::endl;
}
~A() {
std::cout << "A" << id << " dtor" << std::endl;
}
private:
int id;
};
A global1(1); // global first
int main() {
A local1(2);
static A static1(3);
A local2(4);
// Destroy order: local2, local1, static1, global1
}
Common pitfalls
Pitfall 1: Dangling reference
아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const std::string& func() {
std::string s = "Hello";
return s;
}
int main() {
const std::string& ref = func(); // UB
}
// Fix: return by value
std::string func() {
std::string s = "Hello";
return s;
}
Pitfall 2: Dangling pointer
아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
int* func() {
int x = 10;
return &x;
}
int main() {
int* ptr = func(); // UB
}
// Fix: dynamic allocation or return by value
Pitfall 3: Static initialization order
아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// file1.cpp
int globalA = 10;
// file2.cpp
extern int globalA;
int globalB = globalA * 2; // order across TUs unspecified
// Safer: function-local static
int& getGlobalA() {
static int globalA = 10;
return globalA;
}
Pitfall 4: Temporary lifetime
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
std::string getName() {
return "Alice";
}
const char* ptr = getName().c_str(); // UB after full expression
const std::string& name = getName();
const char* ptr = name.c_str(); // OK until name dies
Smart pointers and lifetime
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <memory>
class Resource {
public:
Resource() {
std::cout << "Resource ctor" << std::endl;
}
~Resource() {
std::cout << "Resource dtor" << std::endl;
}
};
void uniquePtr() {
auto res = std::make_unique<Resource>();
}
void sharedPtr() {
auto res1 = std::make_shared<Resource>();
{
auto res2 = res1;
}
}
int main() {
uniquePtr();
sharedPtr();
}
RAII
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <fstream>
#include <mutex>
void writeFile(const std::string& filename) {
std::ofstream file(filename);
file << "Hello";
}
std::mutex mtx;
void criticalSection() {
std::lock_guard<std::mutex> lock(mtx);
// critical section
}
FAQ
Q1: When does lifetime start?
A: After construction completes and initialization finishes.
Q2: When does it end?
A:
- Destructor runs
- Scope ends
deletecalled
Q3: Storage kinds?
A:
- Automatic (local)
- Static (global /
static) - Dynamic (
new/delete) thread_local
Q4: Avoid dangling?
A:
- Smart pointers
- Return by value
- RAII
Q5: Temporary extension?
A: const T& to a temporary extends for the reference’s scope in many cases.
Q6: Learning resources?
A:
- Effective C++
- C++ Primer
- cppreference.com
Related posts (internal links)
Practical tips
Debugging
- Warnings first
Performance
- Measure before tuning
Code review
- Conventions
Practical checklist
Before coding
- Right approach?
- Maintainable?
- Performance?
While coding
- Warnings?
- Edge cases?
- Errors?
At review
- Intent?
- Tests?
- Docs?