내용이 기존 문법과 함께 여기저기 흩어져 있어 보기에 좀 어려워
MSDN을 참고하여 대충 정리하려함.
C++11/14/17 기능에 대한 지원(최신 C++)
: https://msdn.microsoft.com/ko-kr/library/hh567368.aspx
shared_ptr
: https://msdn.microsoft.com/ko-kr/library/hh279669.aspx- 여러곳에서 참조하는 개체의 수명을 관리하기 위한 C++ STL 스마트 포인터
- shared_ptr 를 초기화 한 후에 복사, 함수 인수를 값으로 전달 및 다른 shared_ptr 인스턴스로 할당 가능
- 참조 횟수가 0에 도달하면 참조개체와 내부 제어 블록을 삭제
// Use make_shared function when possible. auto sp1 = make_shared<Song>(L"The Beatles", L"Im Happy Just to Dance With You"); // Ok, but slightly less efficient. // Note: Using new expression as constructor argument // creates no named variable for other code to access. shared_ptr<Song> sp2(new Song(L"Lady Gaga", L"Just Dance")); // When initialization must be separate from declaration, e.g. class members, // initialize with nullptr to make your programming intent explicit. shared_ptr<Song> sp5(nullptr); //Equivalent to: shared_ptr<Song> sp5; //... sp5 = make_shared<Song>(L"Elton John", L"I'm Still Standing");
- 되도록이면 예외 발생 상황에서 문제 없는 make_shared를 사용하여 만들어라.
vector<shared_ptr<MediaAsset>> assets; assets.push_back(shared_ptr<Song>(new Song(L"Himesh Reshammiya", L"Tera Surroor"))); assets.push_back(shared_ptr<Song>(new Song(L"Penaz Masani", L"Tu Dil De De"))); assets.push_back(shared_ptr<Photo>(new Photo(L"2011-04-06", L"Redmond, WA", L"Soccer field at Microsoft."))); vector<shared_ptr<MediaAsset>> photos; copy_if(assets.begin(), assets.end(), back_inserter(photos), [] (shared_ptr<MediaAsset> p) -> bool { // Use dynamic_pointer_cast to test whether // element is a shared_ptr<Photo>. shared_ptr<Photo> temp = dynamic_pointer_cast<Photo>(p); return temp.get() != nullptr; }); for (const auto& p : photos) { // We know that the photos vector contains only // shared_ptr<Photo> objects, so use static_cast. wcout << "Photo location: " << (static_pointer_cast<Photo>(p))->location_ << endl; }
- dynamic_pointer_cast, static_pointer_cast, const_pointer_cast를 사용하여 shared_ptr를 캐스팅할 수 있음.
- shared_ptr는 다음의 방법으로 다른 함수에 전달할 수 있음.
: 값(value)으로 전달 (복사 생성자 호출 => 참조 횟수 증가, 약간 오버 헤드 있음)
: 참조(reference), const 참조로 전달 (참조횟수 증가 안함.)
: 내부 포인터 또는 내부 개체에 대한 참조를 전달 (개체 공유, 단 참조 횟수는 증가하지 않음, 좀 위험.)
- shared_ptr 전달 방법을 결정할 때 고려 해야 하는 것은 호출 수신자(callee)가 소유권을 공유할 수 있는지를 판단해야 함.
: shared_ptr가 call이 완료 될 때 까지 caller, callee 외 다른 소유자로 인해 shared_ptr의 유효함이 보장되면 값으로 전달하고, 보장되지 않는 경우라면 참조를 넘겨 callee가 알아서 판단하도록 한다.
- std:vector<shared_ptr<T>>에서 람다 식 본문 또는 명명된 함수 개체로 전달할 경우 람다, 함수 개체가 포인터를 저장하지 않는다면 참조로 전달한다.
// Initialize two separate raw pointers. // Note that they contain the same values. auto song1 = new Song(L"Village People", L"YMCA"); auto song2 = new Song(L"Village People", L"YMCA"); // Create two unrelated shared_ptrs. shared_ptr<Song> p1(song1); shared_ptr<Song> p2(song2); // Unrelated shared_ptrs are never equal. wcout << "p1 < p2 = " << std::boolalpha << (p1 < p2) << endl; wcout << "p1 == p2 = " << std::boolalpha <<(p1 == p2) << endl; // Related shared_ptr instances are always equal. shared_ptr<Song> p3(p2); wcout << "p3 == p2 = " << std::boolalpha << (p3 == p2) << endl;
- 가리키는 개체의 값을 비교하는 것이 아니라 shared_ptr이 가리키는 개체를 비교해야 함.
Modern Effective C++에서 관련된 chapter는 다음과 같고
더 자세한 내용을 원한다면 책을 꼭 읽는 것을 추천.
단 Modern Effective C++이 처음이라면 Effective C++을 먼저 읽는 것을 추천.
Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14
: http://a.co/0MIIC9k
Item 19: Use std::shared_ptr for shared-ownership resource management.
Item 21: Prefer std::make_unique and std::make_shared to direct use of new.
- std::shared_ptr의 크기는 생 포인터의 두배
: custom deleter를 지정해도 std::shared_ptr 객체의 크기가 변하지 않음.
- 제어 블럭에서 reference count, weak reference count, custom deleter 등을 저장함.
: std::make_shared는 항상 제어 블럭을 생성
: std::unique_ptr, std::auto_ptr로 부터 std:shared_ptr 을 생성하면 제어 블록이 생성
: raw pointer로 std::shared_ptr 생성하면 제어 블록이 생성
단 하나의 raw pointer에서 여러 std::shared_ptr을 생성하면 문제 발생.
- std::shared_ptr로 관리되는 클래스에서 클래스의 this로 부터 shared_ptr을 생성할 때는 shared_from_this()를 사용해야 순환 참조 문제가 없음.
- 참조 횟수의 증가와 감소가 반드시 원자적 연산이어야 함.
댓글 없음:
댓글 쓰기