내용이 기존 문법과 함께 여기저기 흩어져 있어 보기에 좀 어려워
MSDN을 참고하여 대충 정리하려함.
C++11/14/17 기능에 대한 지원(최신 C++)
: https://msdn.microsoft.com/ko-kr/library/hh567368.aspx
unique_ptr
: https://msdn.microsoft.com/ko-kr/library/hh279676.aspx- 일반 C++ 개체에 대한 스마트 포인터가 필요할 경우 사용
- unique_ptr은 포인터를 공유 하지 않고 이동만 가능함.
: 이동 시 메모리 리소스의 소유권이 이전되어 원래 unique_ptr는 더 이상 소유하지 않음.
- 다른 unique_ptr로 복사, 함수에 값으로 전달하거나 사본이 필요한 STL(표준 템플릿 라이브러리) 알고리즘에서는 사용 불가
- unique_ptr을 생성할 경우 되도록이면 make_unique 도우미 함수를 사용
: c++ 14 지원을 위해 compile option(-std=c++14
- <memory> 헤더의 std namespace에 정의 되어 있음.
unique_ptr<Song> SongFactory(const std::wstring& artist, const std::wstring& title) { // Implicit move operation into the variable that stores the result. return make_unique<Song>(artist, title); } void MakeSongs() { // Create a new unique_ptr with a new object. auto song = make_unique<Song>(L"Mr. Children", L"Namonaki Uta"); // Use the unique_ptr. vector<wstring> titles = { song->title }; // Move raw pointer from one unique_ptr to another. unique_ptr<Song> song2 = std::move(song); // Obtain unique_ptr from function that returns by value. auto song3 = SongFactory(L"Michael Jackson", L"Beat It"); }
일반적인 사용 예제, song 변수가 가졌던 개체는 song2로 이전(move)되어 song의 member들은 nullptr이 됨.
void SongVector() { vector<unique_ptr<Song>> songs; // Create a few new unique_ptr<Song> instances // and add them to vector using implicit move semantics. songs.push_back(make_unique<Song>(L"B'z", L"Juice")); songs.push_back(make_unique<Song>(L"Namie Amuro", L"Funky Town")); songs.push_back(make_unique<Song>(L"Kome Kome Club", L"Kimi ga Iru Dake de")); songs.push_back(make_unique<Song>(L"Ayumi Hamasaki", L"Poker Face")); // Pass by const reference when possible to avoid copying. for (const auto& song : songs) { wcout << L"Artist: " << song->artist << L" Title: " << song->title << endl; } }
이동이 불가하므로 vector 로 바로 생성된 개체를 전달함.
vector내 개체를 접근하기 위해 const auto& 로 reference를 참조함.
(const auto song : songs) 은 unique_ptr을 복사하려는 것이므로 컴파일 에러 발생
// Create a unique_ptr to an array of 5 integers. auto p = make_unique<int[]>(5); // Initialize the array. for (int i = 0; i < 5; ++i) { p[i] = i; wcout << p[i] << endl; }
배열에 대한 unique_ptr를 make_unique를 사용해서 생성할 수 있지만 초기화는 별도로..
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 18:Use std::unique_ptr for exclusive-ownership resource management.
Item 21:Prefer std::make_unique and std::make_shared to direct use of new.
참고할 만한 것들을 보면
아래와 같이 Investment를 상속하는 여러 class들이 있을 경우
class Investment { … };
class Stock: public Investment { … };
class Bond: public Investment { … };
class RealEstate: public Investment { … };
template<typename... Ts> // return std::unique_ptr std::unique_ptr<Investment> // to an object created
makeInvestment(Ts&&... params); // from the given args
이렇게 factory 함수인 makeInvestment를 만들어 Investment를 가지는 unique_ptr를 제공할 수 있음.
{
...
auto pInvestment = // pInvestment is of type makeInvestment( arguments ); // std::unique_ptr<Investment>
...
}
이렇게 사용을 하게 될 것이고 생성된 pInvestment는 변수의 scope을 벗어나게 되면 자동으로 소멸 되게 되는게 일반적인 사용 시나리오 일 것임.
함께 unique_ptr는 기본적으로 개체의 소멸자를 호출하겠지만 custom deleter를 직접 지정할 수 있음.
auto delInvmt = [](Investment* pInvestment) // custom
{ // deleter
makeLogEntry(pInvestment); // (a lambda
delete pInvestment; // expression)
};
template<typename... Ts> // revised
std::unique_ptr<Investment, decltype(delInvmt)> // return type
makeInvestment(Ts&&... params)
그리고 c++14의 auto를 사용하게 된다면.. 좀 더 간편할 것임.
template<typename... Ts>
auto makeInvestment(Ts&&... params) // C++14
다만 일반적인 unique_ptr의 사이즈는 raw pointer와 동일하겠지만 custom deleter를 가진 unique_ptr의 사이즈는 한두 word의사이즈가 추가된다. 함께 custom deleter로 function object를 사용하는것 보다 stateless function object인 lambda를 사용하는 것이 unique_ptr의 사이즈를 늘리지 않는다고 함.
그리고 unique_ptr를 생성할 때는 new 대신 std::make_unique를 사용하는 것을 추천하고 있음.
다만 std::make_unique는 c++14에서 지원하고 있어 compile option 설정 필요.
댓글 없음:
댓글 쓰기