C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
분야별 포럼
C++빌더
델파이
파이어몽키
C/C++
프리파스칼
파이어버드
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

자유게시판
세상 살아가는 이야기들을 나누는 사랑방입니다.
[24936] Re:아래 C++11 auto 의문이 더 커졌습니다
빌더(TWx) [builder] 6634 읽음    2014-10-26 20:08
bugfree 님이 쓰신 글 :
: 먼저 답변해주신 박우성님과 빌더님께 감사드립니다
:
: std::map <std::string, int> map;
:
: map에 무작위로 데이타를 넣어두고
:
:
: 1번 방법
:
: for ( const std::pair <std::string, int> & _pair : map)
:          std::cout << _pair.second << std::endl;
:
: 2번 방법
:
: for ( const auto & _pair : map )
:          std::cout << _pair.second << std::endl;
:
: 두가지 방법으로 출력하는 코드에서 auto의 타입이
: <const std::string, int>라는 빌더님의 설명에 좀 놀랐습니다
: auto가 단순히 타이핑 노가다만 줄여주는거로 알았는데
: 그게 아니었네요
:
: 제가 의문이 더 커지게 된건 박우성님 답변내용 때문인데요
:
: <const std::string, int>에서 const가 빠지는 바람에
: string 값의 복사가 일어나서 그 만큼 시간이 더 걸린다고  하셨습니다
:
: 근데 제가 알고있기론, 그리고 테스트 해본 결과에 따르면
:
: void func (const std::string str) 과
: void func (std::string str) 은
:
: const 있고 없고 상관없이 두 경우 다 복사가 일어납니다
:
: class C {}; 가 있을 때
:
: func (const C obj) 와 func (C obj) 도 호출해보면 마찬가집니다
:
: const는 값을 변경하지 못하게 금지할뿐, 포인터가 아니라
: 두 경우 다 복사가 일어나서 다를게 없잖아요
:
: auto를 사용한 속도가 더 빠른 이유에 의문점이 더 커졌습니다
:







박성우님의 답변내용을 지금 다시 읽어보니...
const가 빠진 결과 string 객체의 복사가 일어나서 그 만큼 시간이 더 걸린다는 문맥으로 읽혀지긴 하네요.



속도가 차이나는 것은... const가 빠져서 string 객체의 복사가 일어났기 때문이 아닙니다.
<const std::string, int> 와 <std::string, int>는...
레퍼런스 또는 포인터에 의한 참조가 아닌.. 값에 의한 참조이기 때문에 const가 있든 없든...
말씀하신 대로.. 두 경우 모두 복사는 일어 납니다.

따라서 두 경우 모두 복사가 일어나는 같은 조건이기 때문에 이 자체가 속도 차이를 나게 하는 요인은 아닙니다.


1번 방법(auto를 사용하지 않은)이 더 느린 이유는... 컴파일러가 Temporary 객체를 생성하기 때문이라고 먼저 답변에서
말씀드렸었는데...  다시 풀어서 얘기를 해보죠.


auto를 사용한 문장을 살펴 봅시다.

for ( const auto &_pair : map )
       std::cout << _pair.second << std::endl;


위와 같이 range-based for 문장에서 _pair가 Value 타입이 아닌, Reference 타입으로 지정되어 있기 때문에 컨테이너 map의
Element인 pair에 대한 값의 복사가 일어날 필요가 없습니다. 그래서 컴파일러는 단순히 Iterator를 이용해서 레퍼런스 타입으로
_pair를 참조하는 코드를 생성하면 그만 입니다.

그러나...

auto를 사용하지 않은 1번 방법은...

for ( const std::pair <std::string, int> &_pair : map )
         std::cout << _pair.second << std::endl;


컨테이너에서 정의 되어있는 Element의 실제타입 <const Key, Value>가 아닌, 사용자에 의해서 <Key, Value> 타입으로 요구된
경우기 때문에... _pair가 Reference 타입으로 지정되어 있음에도 불구하고, 컴파일러가 타입변환을 위한 Temporary 객체 생성을
시도하게 됩니다.

여기서 Temporary 객체는 타입매칭을 위해 컴파일러에 의해서 생성되는 valu type의 pair<Key, Value> 이고 Reference 타입인
_pair에 바인딩 하게 됩니다. Temporaray 객체가 의도치 않게 생성되는 바람에 Element인 pair에 결합 되어있는 string 객체도
덩달아 불필요하게 생성되는 사이드 이펙트가 발생하게 됩니다.


결론...

const가 빌미를 제공한 건 맞지만...

여기서 속도 차이가 일어나는 근본적인 원인은... const 가 없어서 string 객체의 복사가 일어났기 때문이 아니라...
range-based for 루프 문장에서 타입매칭을 위해 Temporary 객체가 반복적으로 생성/소멸되기 때문 입니다.

컴파일러에 의해서 Temporary 객체가 생성되지 않도록 몇가지 테크닉을 이용할 수도 있지만 실제 코딩을 하다 보면
Temporary 객채의 생성을 피할 수 없는 경우도 있기 때문에... 이런 경우에 템플릿이나 클래스를 구현할 땐... 컴파일러가
C++11을 지원한다면 copy constructor 호출로 인한 복제비용을 줄이기 위해 r-value reference를 이용한 move constructor도
함께 구현해 주는 게 효과적 입니다.

bugfree [bugfree]   2014-10-26 21:20 X
10년 묵은 체증이 한방에 뻥뚫리는 기분이네요
제가 갖고있던 의문을 명쾌하게 풀어 주셔서
빌더님 너무 감사합니다

+ -

관련 글 리스트
24935 아래 C++11 auto 의문이 더 커졌습니다 bugfree 5322 2014/10/26
24936     Re:아래 C++11 auto 의문이 더 커졌습니다 빌더(TWx) 6634 2014/10/26
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.