Upload
seok-joon-yun
View
440
Download
2
Embed Size (px)
Citation preview
Effective Modern C++ Study C++ Korea
Effective Modern C++ Study C++ Korea 3
불필요한 복사를 줄이기
위해 레퍼런스로 받음.
R-Value는 받을 수 없음.
Effective Modern C++ Study C++ Korea 4
Effective Modern C++ Study C++ Korea
w의 타입은 Widget&
w의 타입은 Widget&&
Effective Modern C++ Study C++ Korea 6
• R-Value Reference • Universal Reference
std::vector<T>의 T는 param과 독립적.
Effective Modern C++ Study C++ Korea 7
• Universal Reference 아님.
• R-Value만 받을 수 있다.
• 타입 추론이 발생
하지 않는다.
Effective Modern C++ Study C++ Korea 8
Effective Modern C++ Study C++ Korea 9
Effective Modern C++ Study C++ Korea 11
Effective Modern C++ Study C++ Korea 12
Effective Modern C++ Study C++ Korea 13
Effective Modern C++ Study C++ Korea 14
Effective Modern C++ Study C++ Korea 15
Effective Modern C++ Study C++ Korea 16
//지역변수 n이 w.setName으로 이동
Effective Modern C++ Study C++ Korea 17
Effective Modern C++ Study C++ Korea 18
Effective Modern C++ Study C++ Korea 19
Effective Modern C++ Study C++ Korea 20
Effective Modern C++ Study C++ Korea 21
Effective Modern C++ Study C++ Korea 22
Effective Modern C++ Study C++ Korea 23
Effective Modern C++ Study C++ Korea 24
Effective Modern C++ Study C++ Korea 25
Effective Modern C++ Study C++ Korea 26
Effective Modern C++ Study C++ Korea 27
RVO
Effective Modern C++ Study C++ Korea 28
A : 조건 2에 부합하지 않음
Effective Modern C++ Study C++ Korea 29
Effective Modern C++ Study C++ Korea 30
Effective Modern C++ Study C++ Korea 31
Effective Modern C++ Study C++ Korea 33
std::multiset<std::string> History; // Global Log History
void Log(const std::string& item)
{
History.emplace(item);
}
std::string name("Luna"); Log(name);
Log(std::string("Star"));
Log("Seokjoon");
// Parameter로 name이라는 변수가 사용됨. // L-Value가 emplace로 COPY
// Parameter로 R-Value가 전달되었지만, // item이 L-Value라서 결국 emplace로 COPY
// Parameter로 R-Value가 전달되었지만, // 임시로 std::string 개체가 만들어져서 결국 emplace로 COPY
Universal Reference + std::forward 면 efficient하게 할 수 있다.
Effective Modern C++ Study C++ Korea 34
std::multiset<std::string> History; // Global Log History
template<typename T>
void Log(T&& item)
{
History.emplace(std::forward<T>(item));
}
std::string name("Luna"); Log(name);
Log(std::string("Star"));
Log("Seokjoon");
// L-Value std::string를 emplace로 COPY (기존과 동일)
// R-Value를 emplace로 MOVE
// std::string를 item에서 임시로 만드는 것이 아니라 // multiset 안에다가 직접 생성함
하지만 std::string가 아닌 Indirect로 값을 받아야 할 경우가 있다면 ???
Effective Modern C++ Study C++ Korea 35
std::string GetItemFromTable(int idx);
void Log(int idx)
{
History.emplace(GetItemFromTable( ));
}
Log(22);
short s = 22;
Log(s);
// Call int overload
// Compile Error : // can’t convert argument // ‘short’ to std::string ctor
Universal Reference Overload 함수는 C++에서 가장 탐욕스러운 함수이다. (닥치는 대로 호로록)
• Instantiation of template (자세한 설명 생략)
• Overload Resolution Rule (자세한 설명 생략)
(위 2가지에 대해서 모른다면 검색해서 알아 보도록… Right Now !!!)
• Parameter가 int인 경우 정확히 int Overload 함수를 실행하지만,
• short인 경우는 T&&을 이용하여 Instantiation이 가능하다.
• Overload Resolution Rule에 의해서 template 함수가 호출되며,
Compile Error를 발생시킨다.
해결방법은 ? Perfect Forwarding Constructor (라고는 하는데 이번 item에서는 해결이 안된다.)
Effective Modern C++ Study C++ Korea 36
class Item {public:
template<typename T>
explicit Item(T&& data) // Perfect Forwarding ctor
: value(std::forward<T>(data)) {}
explicit Item(int idx) // int ctor
: value(GetItemFromTable(idx)) {}
private:
std::string value;
};
• 하지만, int를 제외한 나머지 타입 (std::size_t, short, long …)에 대해서는 Universal Reference Constructor가 호출
• 심지어 생성자에 다른 Item 개체를 넣어도 Universal Reference Constructor 생성자가 ???
아 왜 ?
Effective Modern C++ Study C++ Korea 37
Item ME("Luna");
auto CloneofME(ME);
Item(const Item& SRC); // Copy ctor (Compiler-generated)
Item(Item&& SRC); // Move ctor (Compiler-generated)
explicit Item(Item& ) // Instantiated from Perfect Forwarding template: value(std::forward<Item&>(data)) {}
• Overload Resolution Rule에 따라 본다면, 뭐가 가장 parameter에 똑같이 매칭될까 ?
• 그럼 해결 방법은 ?
Compiler는 C++의 Rule을 반드시 지키도록 맹세하였다. (융통성 없는 놈하고는…)
const Item ME("Luna"); // Object is now const
auto CloneofME(ME);
Effective Modern C++ Study C++ Korea 38
class ItemEx : public Item {public:
ItemEx(const ItemEx& item) // Copy ctor
: Item(item) {} // Calls base class forward ctor
ItemEx(ItemEx&& item) // Move ctor
: Item(std::move(item)) {} // Calls base class forward ctor
};
• Derived Class에서 Base Class로 Item이 아닌 ItemEx로 전달하기 때문이다.
Effective Modern C++ Study C++ Korea 39
• Universal Reference를 Overload하면 뭘 상상하든 그 이상으로
훨씬 더 자주 맨날맨날 허구언날 시도때도 없이
Universal Reference Overload가 호출된다.
• Perfect Forwarding Constructor도 마찬가지다. 아니 이놈은 더하다.
non-const L-Value와의 궁합이 COPY Constructor보다 더 잘 맞고,
Derived class의 COPY, MOVE Constructor의 호출도 가로채버린다.
• 그냥 Universal Reference Overload 와 Perfect Forwarding Constructor를 쓰지마라.
http://devluna.blogspot.kr/2015/03/item-26-universal-reference.html