[2026] C++ Object Lifetime: Storage Duration, RAII, and Dangling

[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
  • delete called

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

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?

Keywords

C++, lifetime, storage duration, RAII, memory

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3