effective modern c++ mva item 18 use std::unique_ptr for exclusive-ownership resource management...
TRANSCRIPT
Effective Modern C++ StudyC++ Korea5
1. Single Object 인지Array인지알수없다.
2. Pointer 사용후 delete해야하는지알수없다.다른곳에서사용중인데 delete하면 -> run time error
사용하는곳이없는데 delete안하면 -> memory leak
3. delete로지워야하는지, delete []로지워야하는지알수없다.
4. delete, delete [] 둘중뭐로해제해도 error 없이해제해준다.하지만잘못했을땐나중에 run time error 가…
5. 이미해제되었는지(dangling pointer) 여부를알수없다.정확한해제방법을알아도 dangling pointer를해제하면 -> run time error
Effective Modern C++ StudyC++ Korea6
1. std::auto_ptr
- C++98부터있었으나별로사용되지않았음
(C++98에는Move Sementics가없어서 MOVE를못하고COPY로수행되었음)
- C++11에서도잘사용되지는않음
2. std::unique_ptr- 개체를공유하지않고, 유일할소유권으로관리하기위한 Smart Pointer
- 모든면에서 std::auto_ptr보다좋음
Effective Modern C++ StudyC++ Korea7
3. std::shared_ptr
- 개체를공유하면서관리하기위한 Smart Pointer
- 해당개체를아무도사용하지않을때자동으로해제해줌
4. std::weak_ptr- std::shared_ptr의순환참조를방지
- dangling pointer 여부확인이가능
Effective Modern C++ StudyC++ Korea9
1. Raw Pointer 만큼작고빠르며, 거의비슷한방법으로사용이가능
custom deleter를사용안하면크기도같음
2. Default로는개체해제시 delete를사용하지만, custom deleter도가능
3. 개체에대해서독점소유권을가지며, 포인터해제시개체도해제됨
4. MOVE only 타입
Effective Modern C++ StudyC++ Korea10
user
① 개체를 내놓아라~
Factory② 옜다. 개체.
(사실은 개체가 아니라 Pointer만 준건 비밀 ?)
③ 사용 후 해제의 의무
(다 알거든. 개체가 아니라 Pointer만 준거. 근데 해제는 나보고 ?)
std::unique_ptr의동작과완벽하게일치 + 자동해제는 뽀나스~
Effective Modern C++ StudyC++ Korea12
class ElvenUnit { ... };class TempleKnight : public ElvenUnit { ... };class ElemetalSummoner : public ElvenUnit { ... };class Elder : public ElvenUnit { ... };
template<typename... Ts>std::unique_ptr<ElvenUnit> MakeElvenUnit(Ts&&... params){
std::unique_ptr<ElvenUnit> pElf(nullptr); // make null unique_ptrif ( /*is TK*/) { pElf.reset(new TempleKnight(std::forward<Ts>(params)...)); }else if ( /*is ES*/) { pElf.reset(new ElemetalSummoner(std::forward<Ts>(params)...)); }else if ( /*is Ed*/) { pElf.reset(new Elder(std::forward<Ts>(params)...)); }
return pElf;}
{
auto pElf = MakeElvenUnit( arguments ); // std::unique_ptr<ElvenUnit>...
} // destroy *pElf
Effective Modern C++ StudyC++ Korea13
std::vector<std::unique_ptr<ElvenUnit>> ElvenArmy;
{auto pElf = MakeElvenUnit( arguments ); // std::unique_ptr<ElvenUnit>ElvenArmy.emplace_back(std::move(pElf)); // set pElf to null
}
Effective Modern C++ StudyC++ Korea15
1. 함수 Pointer 또는 Lambda 로개체삭제방법설정이가능
default로는 delete가사용
2. 원래 std::unique_ptr의크기는 Raw Pointer와같이 1 word 지만,
deleter에대한 Pointer가추가로필요해져서 2 word가됨
stateless function object (e.g. captureless lambda )의경우는크기패널티가없음
3. std::unique_ptr타입의일부
custom deleter의 state 만큼 std::unique_ptr의크기가커짐
고로 deleter는 function 보다는 captureless lambd가더바람직
Effective Modern C++ StudyC++ Korea16
auto DieElf = [](ElvenUnit* pElf) { // custom deleter (using lambda expression)AddGuildExp(pElf);delete pElf;
};
template<typename... Ts>std::unique_ptr<ElvenUnit, decltype(DieElf)> MakeElvenUnit(Ts&&... params){
std::unique_ptr<ElvenUnit, decltype(DieElf)> pElf(nullptr, DieElf); // make null unique_ptr
if ( /* Temple Knight 를 만들 조건이면 */) {pElf.reset(new TempleKnight(std::forward<Ts>(params)...));
}else if ( /* Elemental Summoner 를 만들 조건이면 */) {
pElf.reset(new ElemetalSummoner(std::forward<Ts>(params)...));}else if ( /* Elder를 만들 조건이면 */) {
pElf.reset(new Elder(std::forward<Ts>(params)...));}return pElf;
}
Effective Modern C++ StudyC++ Korea17
template<typename... Ts>auto MakeElvenUnit(Ts&&... params){
auto DieElf = [](ElvenUnit* pElf) { // custom deleter (using lambda expression)AddGuildExp(pElf);delete pElf;
};
std::unique_ptr<ElvenUnit, decltype(DieElf)> pElf(nullptr, DieElf); // make null unique_ptr
if ( /* Temple Knight 를 만들 조건이면 */) {pElf.reset(new TempleKnight(std::forward<Ts>(params)...));
}else if ( /* Elemental Summoner 를 만들 조건이면 */) {
pElf.reset(new ElemetalSummoner(std::forward<Ts>(params)...));}else if ( /* Elder 를 만들 조건이면 */) {
pElf.reset(new Elder(std::forward<Ts>(params)...));}return pElf;
}
Effective Modern C++ StudyC++ Korea18
auto DieElf = [](ElvenUnit* pElf) // stateless lambda{
AddGuildExp(pElf);delete pElf;
};
template<typename... Ts>std::unique_ptr<ElvenUnit, decltype(DieElf)> // return type has size of EvenUnit*MakeElvenUnit(Ts&&... params);
void DieElf(ElvenUnit* pElf) // function{
AddGuildExp(pElf);delete pElf;
};
template<typename... Ts>std::unique_ptr<ElvenUnit, void (*)(ElvenUnit*)> // return type has size of EvenUnit*MakeElvenUnit(Ts&&... params); // + at least size of function pointer !
Effective Modern C++ StudyC++ Korea20
1. Single Object (std::unique_ptr<T>), 배열 (std::unique_ptr<T[]>)
둘다사용이가능
std::unique_ptr API 는각각다르게처리
Single Object 에대해서는 Index 연산자 [ ] 가없고,
배열에대해서는 dereference 연산자 ( * , -> )가없음
2. Std::unique_ptr은 std::shared_ptr로쉽게캐스팅
반대는불가능
그래서 Factory method에서일단 std::unique_ptr로받는게더적절
Effective Modern C++ StudyC++ Korea22
• std::unique_ptr은 작고, 빠르고, MOVE-only 스마트 포인터이며,
자원을 독점적으로 관리해 줍니다.
• Default로는 개체 해제에 delete를 사용하지만,
custom deleter를 사용 할 수도 있습니다.
Stateless lambda를 사용하면 크기 패널티가 없지만,
그렇지 않은 경우는 pointer 1개 크기 + state 크기만큼 더 커집니다.
• std::unique_ptr에서 std::shared_ptr로쉽게 캐스팅이 가능합니다.
그 반대는 절대로 안됩니다.
http://devluna.blogspot.kr/2015/04/item-18-stdunqiueptr.html