2018년 5월 21일 월요일

C++ 11/14 관련 내용 대충 정리, 개체 수명 및 리소스 관리

최신 C++을 공부하려 책을 보긴 했었는데
내용이 기존 문법과 함께 여기저기 흩어져 있어 보기에 좀 어려워
MSDN을 참고하여 대충 정리하려함.

C++11/14/17 기능에 대한 지원(최신 C++)
https://msdn.microsoft.com/ko-kr/library/hh567368.aspx


개체 수명 및 리소스 관리

https://msdn.microsoft.com/ko-kr/library/hh438473.aspx


- managed language와는 달리 C++은 gabage collection(GC)이 없음.
- C++에서 resource 관리는 object lifetime과 밀접한 관련이 있음
 : memory, non-memory resources들은 소멸자를 통해서 관리 될 수 있음.


개념

- object-lifecycle 관리에서 중요한 것은 캡슐화임.
 : object가 소유한 resource는 무엇이고 어떻게 해제하는지를 알 필요가 없고
   그냥 object를 삭제하면 끝이여야 함.
 : C++ 에서 개체가 scope을 벗어날 때
   정해진 시간에 생성된 역순으로 소멸되며
   정해진 순서에 따라 개체의 부모 개체와 멤버 변수들이 소멸된다.
 : smart pointers(unique_ptr, shared_ptr)나 STL container들도 new/delete, new[]/delete[]를 캡슐화 하고 있듯이 중요함.

- 소멸자(Destructor)는 resource release 측면에서 중요하다.
 : Memory나 files, sockets과 같은 non-memory resources들을 개체에서
   필요에 의해 사용할 경우, 개체가 소멸될 때 소멸자에서 사용한 resource들을 해제하는 것은 당연하다.

- 프로그램에서 개체의 소유는 DAG(Directed Acylic Graph, 방향을 가지되 자신으로 돌아 올 수 없는) 형태여야 한다.
 : DAG의 형태로 순환 참조가 없는 소유 형태에서 각 노드가 소멸자를 가진 개체가 된다면 resource leak이 발생할 수 없다.


Heap-based lifetieme


heap 기반의 개체 관리는 smart pointer(shared_ptr)를 사용하고 순환 참조를 피하기 위해서는 weak_ptr를 사용하라.

void func() {  
  
auto p = make_shared<widget>(); // no leak, and exception safe  
...  
p->draw();   
  
} // no delete required, out-of-scope triggers smart pointer destructor  
  

하나뿐인 소유권 관리를 위해서는 unique_ptr와 Pimpl idiom을 사용할 수 있다.

unique_ptr<widget> p(new widget()); 

또한 소유하지 않는 관찰의 측면에서 raw pointer를 사용할 수 있으나 leak은 없지만 dangle pointer가 될 수 있음.

class node {  
  ...  
  vector<unique_ptr<node>> children; // node owns children  
  node* parent; // node observes parent, which is not a concern  
  ...  
};  
node::node() : parent(...) { children.emplace_back(new node(...) ); }  
  


Stack-based lifetime


modern C++에서는 stack-based scope은 높은 효율성을 갖는 stack lifetime, data member lifetime을 기반한 강력한 코드를 작성하는데 효과적인 방법이다. 이에 반해  raw pointer를 사용하여 heap 기반 object lifetime를 관리하는 방법은 leak과 비효율적이다.

class widget {  
private:  
  gadget g;   // lifetime automatically tied to enclosing object  
public:  
  void draw();  
};  
  
void functionUsingWidget () {  
  widget w;   // lifetime automatically tied to enclosing scope  
              // constructs w, including the w.g gadget member  
  …  
  w.draw();  
  …  
} // automatic destruction and deallocation for w and w.g  
  // automatic exception safety,   
  // as if "finally { w.dispose(); w.g.dispose(); }"  
  

 단  global static, local static에서의 예외 상황은 디버그 하기 힘든 경우가 있고 동시성 측면에서 안전하지 않고 다형성을 사용할 경우 객채의 생성, 소멸 관련 문제가 발생할 수 있음.


댓글 없음:

댓글 쓰기