일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 보편 참조
- 예외
- effective modern c++
- Effective c++
- c++
- UE4
- 게임
- 티스토리챌린지
- 오블완
- virtual function
- reference
- 참조자
- operator new
- resource management class
- universal reference
- 영화
- 스마트 포인터
- 영화 리뷰
- effective stl
- 반복자
- iterator
- Smart Pointer
- 암시적 변환
- exception
- more effective c++
- 상속
- std::async
- lua
- implicit conversion
- 언리얼
Archives
- Today
- Total
스토리텔링 개발자
[Effective Modern C++] 29. 이동 연산이 없다고 가정하기 본문
Effective C++/Effective Modern C++
[Effective Modern C++] 29. 이동 연산이 없다고 가정하기
김디트 2025. 3. 24. 11:58728x90
항목 29. 이동 연산이 존재하지 않고, 저렴하지 않고, 적용되지 않는다고 가정하라
개요
- 이동 의미론이 의미를 가지고, 성능을 개선시킬 수 있는 것은 사실이다.
- 하지만, 그렇지 않은 상황도 분명 존재한다.
이동 연산이 없다
- 이동 의미론을 지원하지 않는 타입들이 많다
- C++11의 표준 라이브러리는 이동을 복사보다 빠르게 구현할 수 있는 타입에 대해서만 이동 연산들을 추가했다.
- 반대로 말하면 구현되지 않은 타입도 존재한다는 뜻이다.
- 구현되지 않았더라도 C++11이 자동으로 이동 연산을 작성해 주니 성능 향상은 발생한다?
- 이동 연산이 자동 생성되지 않는 경우들이 존재한다.
이동이 더 빠르지 않다
- 이동을 명시적으로 지원하는 타입이라도 이득이 생각만큼 크지 않을 수 있다.
- 예컨대 c++1 표준 라이브러리의 모든 컨테이너는 이동을 지원한다.
- 하지만 모든 컨테이너의 이동이 저렴하다고 가정하면 안된다.
- 컨테이너에 담긴 내용을 정말 저렴하게 이동하는 방법이 없는 컨테이너도 있고,
- 컨테이너가 제공하는 저렴한 이동 연산이 요구하는 까다로운 조건을 만족시킬 수 없는 경우도 있다.
- std::array
- 원시 배열에 STL 인터페이스를 씌운 것이다.
- 보통의 컨테이너는 요소들의 포인터를 관리하지만, std::array는 요소 자체를 관리한다.
- std::array는 결국 이동과 복사 모두 계산 복잡도가 선형(linear)이다.
- 결국 이동으로 얻는 성능상 이점이 아주 미미하다.
- 컨테이너를 이동하는 것이 포인터를 복사하는 것만큼이나 저렴하다!는 주장과는 거리가 멀다.
- std::string
- 상수 시간 이동과 선형 시간 복사를 제공한다.
- 이동이 복사보다 빠를 것 같지만, 반드시 그렇진 않다.
- 작은 문자열 최적화가 적용되는 작은 문자열에는 이동이 복사보다 빠르지 않다.
- 대체로 이동이 복사보다 빠른 것은 포인터 하나만 복사하면 되기 때문인데
- 이 경우 그런 요령을 적용할 수 없기 때문이다.
- 작은 문자열 최적화(small string optimization, SSO)
- 작은 문자열(용량이 15자 이하)을 std::string 객체 안의 버퍼에 저장하고,
- 힙에 할당한 저장소는 사용하지 않는다.
- 짧은 문자열들이 빈번하고 통상적으로 쓰인다는 가정.
이동을 사용할 수 없다
- 빠른 이동 연산을 지원하는 타입이지만, 복사가 일어나는 경우가 있다.
- 표준 라이브러리의 일부 컨테이너 연산들은 강한 예외 안전성을 보장한다.
- 그 보장에 의존하는 구식 C++98 코드를 C++11에서 컴파일에도 안정성을 보장하기 위해서
- 이동 연산들이 예외를 던지지 않음이 확실한 경우에만 복사 연산을 이동 연산으로 자동 대체한다. (항목 14 참조)
원본 객체가 lValue이다
- 아주 드문 경우(항목 25 참조)지만,
- 오직 rValue만 이동 연산의 원본이 될 수 있는 경우도 있다.
결론
- 이동 연산들이 존재하지 않고, 저렴하지 않고, 적용되지 않는다고 '가정'하자.
- 일반적 코드(이를테면 템플릿)에서는 대체로 그런 가정을 하는 편이 좋다.
- 코드에 쓰이는 모든 타입을 알 수 없기 때문이다.
- 코드가 사용하는 구체적인 타입을 미리 알 수 있고, 그 타입들의 특징이 바뀌지 않음을 확신한다면
- 위와 같은 가정을 굳이 할 필요가 없다.
728x90
'Effective C++ > Effective Modern C++' 카테고리의 다른 글
[Effective Modern C++] 31. 람다 기본 캡쳐 모드 지양하기 (0) | 2025.04.01 |
---|---|
[Effective Modern C++] 30. 완벽 전달(Perfect Forwarding)이 실패하는 경우 (0) | 2025.03.25 |
[Effective Modern C++] 28. 참조 축약(reference collapsing) (0) | 2025.03.21 |
[Effective Modern C++] 27. 보편 참조 오버로드를 피하는 기법 (0) | 2025.03.18 |
[Effective Modern C++] 26. 보편 참조 오버로드 금지 (0) | 2025.03.14 |
Comments