5. Effective Modern C++ Study
C++ 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
6. Effective Modern C++ Study
C++ Korea6
1. std::auto_ptr
- C++98부터 있었으나 별로 사용되지 않았음
(C++98에는 Move Sementics가 없어서 MOVE를 못하고 COPY로 수행되었음)
- C++11에서도 잘 사용되지는 않음
2. std::unique_ptr
- 개체를 공유하지 않고, 유일할 소유권으로 관리하기 위한 Smart Pointer
- 모든 면에서 std::auto_ptr보다 좋음
7. Effective Modern C++ Study
C++ Korea7
3. std::shared_ptr
- 개체를 공유하면서 관리하기 위한 Smart Pointer
- 해당 개체를 아무도 사용하지 않을 때 자동으로 해제 해줌
4. std::weak_ptr
- std::shared_ptr의 순환 참조를 방지
- dangling pointer 여부 확인이 가능
8.
9. Effective Modern C++ Study
C++ Korea9
1. Raw Pointer 만큼 작고 빠르며, 거의 비슷한 방법으로 사용이 가능
custom deleter를 사용 안하면 크기도 같음
2. Default로는 개체 해제시 delete를 사용하지만, custom deleter도 가능
3. 개체에 대해서 독점 소유권을 가지며, 포인터 해제시 개체도 해제됨
4. MOVE only 타입
10. Effective Modern C++ Study
C++ Korea10
user
① 개체를 내놓아라~
Factory② 옜다. 개체.
(사실은 개체가 아니라 Pointer만 준건 비밀 ?)
③ 사용 후 해제의 의무
(다 알거든. 개체가 아니라 Pointer만 준거. 근데 해제는 나보고 ?)
std::unique_ptr의 동작과 완벽하게 일치 + 자동해제는 뽀나스~
11. Effective Modern C++ Study
C++ Korea11
elf
Temple Knight Elemental Summoner Elder
12. Effective Modern C++ Study
C++ 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_ptr
if ( /*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
13. Effective Modern C++ Study
C++ 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
}
14.
15. Effective Modern C++ Study
C++ 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가 더 바람직
16. Effective Modern C++ Study
C++ 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;
}
17. Effective Modern C++ Study
C++ 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;
}
18. Effective Modern C++ Study
C++ 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 !
19.
20. Effective Modern C++ Study
C++ 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로 받는게 더 적절
21.
22. Effective Modern C++ Study
C++ 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
icysword77@gmail.com