6. 방법 2 - 단점
- 템플릿이기 때문에 구현코드를 항상
헤더파일에 작성해야 한다
- 목적 코드에는 이 템플릿의 서로 다른
인스턴스가 여러 개 포함될 수 있다
widget.addName("ddd");
widget.addName(string("ddddd"));
7. 방법 2 - 단점
- 보편 참조로는 전달할 수 없는 타입이 존재
nullptr, 중괄호 이니셜라이저, 비트필드,
선언만 된 정수 static const 및 constexpr 자료 멤버,
오버로딩된 함수 이름과 템플릿 이름
- 허용되지 않는 타입을 전달했을 경우
오류메시지를 이해하기 힘들다
9. 비용 비교
방법1 - 중복적재
Widget w;
String name(“Bart”);
w.addName(name); // 복사 1회
w.addName(name + “Jenne”); // 이동 1회
10. 비용 비교
방법2 – 보편 참조
Widget w;
String name(“Bart”);
w.addName(name); // 복사 1회
w.addName(name + “Jenne”); // 이동 1회
11. 비용 비교
방법3 – 값 전달
Widget w;
String name(“Bart”);
w.addName(name); // 복사 1회, 이동 1회
w.addName(name + “Jenne”); // 이동 2회
12. 이동이 저렴하고 항상 복사되는
복사 가능 매개변수에 대해서는
값 전달을 고려하라
이동 비용이 싸고
복사 가능한 타입이고
전달한 값을 함수 내 에서 항상 복사한다면
방법3을 생각 해 볼만 하다
13. 방법3을 선택할 때 주의할 점
- 다른 방법들에 비해 비용이 크다
- 복사 가능 매개변수에 대해서만
값 전달을 고려해야 한다
이동 전용 매개변수는 이동용 함수 하나만 있으면 된다
widget.setPtr("Morden C++");
void setPtr(unique_ptr<string>&& ptr ) // 이동 1회
void setPtr(unique_ptr<string> ptr ) // 이동 2회
14. 방법3을 선택할 때 주의할 점
- 이동 비용이 저렴해야한다
다른 방법에 비해 이동 횟수가 1회 늘었기 때문
- 항상 복사되어야 한다
복사가 되지 않는다면 쓸데없이 생성자만 호출 됨
15. 방법3을 선택할 때 주의할 점
- 동적 할당에 의존하는 타입은 적절하지 않다
std::string, std::vector
위 함수는 text가 newPwd보다 길이가 작을 때만 메모리
재할당과 해제가 일어나지만 아래함수는 항상 발생한다
16. 방법3을 선택할 때 주의할 점
- 잘림 문제
파생 클래스를 베이스 클래스에 할당하면 베이스 클래스에
해당되는 값들은 복사되지만 확장된 값들은 저장할 곳이
없어서 복사되지 않는 현상
C++11에서도 여전히 존재
class Widget {…};
class SpecialWidget : public Widget {…};
void processWidget(Widget w);
SpecialWidget sw;
processWidget(sw); // Widget 으로 인식됨!
17. 기억해 둘 사항들
- 이동이 저렴하고 항상 복사되는 복사 가능
매개변수에 대해서는 값 전달이 참조 전달
만큼이나 효율적이고, 구현하기가 더 쉽고,
산출되는 목적 코드의 크기도 더 작다
- 왼값 인수의 경우 값 전달(복사 생성) 다음의
이동 배정은 참조 전달 다음의 복사 배정보다
훨씬 비쌀 가능성이 있다
18. 기억해 둘 사항들
- 값 전달에서는 잘림 문제가 발생할 수 있으므
로, 일반적으로 기반 클래스 매개 변수 형식에
대해서는 값 전달이 적합하지 않다