본문으로 건너뛰기
Previous
Next
C++ Object Lifetime: Storage Duration, RAII, and Dangling

C++ Object Lifetime: Storage Duration, RAII, and Dangling

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).

void func() {
    int x = 10;  // x begins
    // x is usable here
}  // x ends

Storage duration

Here is the func implementation:

// 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

#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

#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

#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

#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

#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

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

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

// 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

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

#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

#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


같이 보면 좋은 글 (내부 링크)

이 주제와 연결되는 다른 글입니다.


이 글에서 다루는 키워드 (관련 검색어)

C++, Lifetime, Storage Duration, RAII, Memory 등으로 검색하시면 이 글이 도움이 됩니다.