range base for는 다 좋은데 조금 아쉬운 부분이 있습니다.

그것은 앞에서 뒤로 순차적으로만 접근이 된다는 것입니다.

때로는 뒤에서부터 시작해야 할 때가 있습니다.

 

이때는 일반적인 방법으로는 안되고 boost 라이브러리의 도움을 받으면 할 수 있습니다.

boost 라이브러리의 boost::adaptors::reverse 를 사용합니다.

 

< 예제. 4 >

#include <iostream>

#include <boost/range/adaptors.hpp>

 

int main()

{

           int NumberList[] = { 1, 2, 3 };

 

           for (auto i : boost::adaptors::reverse(NumberList))

           {

                     std::cout << i << "  ";

           }

 

           std::cout << std::endl << std::endl;

 

 

 

           std::vector<int> vecNumberList;

           vecNumberList.push_back( 1 );

           vecNumberList.push_back( 2 );

           vecNumberList.push_back( 3 );

 

           for (auto i : boost::adaptors::reverse(vecNumberList))

           {

                     std::cout << i << "  ";

           }

 

           std::cout << std::endl;

 

           return 0;

}

 

< 실행 결과 >


저작자 표시
신고
by 흥배 2012.10.15 09:00

range base for에서 데이터셋의 요소를 변경할 수 있을까요?

정답은 있을 수도 있고, 없을 수도 있습니다.

 

앞 선 예제 코드에서는

for( auto i : NumberList )

이런 식으로 사용했는데 이런 경우 i의 값을 for 문 안에서 변경 할 수 있지만 for 문을 나오면 NumberList의 요소에는 적용되지 않습니다.

 

만약 요소의 값을 변경하고 싶다면 참조를 사용하면 됩니다.

for( auto &i : NumberList )

이런 식으로 하면 for 문을 나와도 NumberList의 요소는 변경이 적용되어 있습니다.

 

그런데 만약 for 문에서 요소 값을 변경하지 못하도록 하려면 const를 사용합니다.

for( auto const i : NumberList )

 

for 문에서 데이터셋 요소를 접근할 때는 임시 변수를 만들기 때문에 이 비용을 줄이고 싶다면 참조를 사용하면 좋습니다.

또 만약 요소의 값을 변경하지 못하도록 하고 싶다면 const 참조를 사용합니다.

for( auto const &i : NumberList )

 


< 예제. 3 >

#include <iostream>

#include <vector>

 

int main()

{

           std::vector<int> NumberList;

           NumberList.push_back( 1 );

           NumberList.push_back( 2 );

           NumberList.push_back( 3 );

          

           for( auto i : NumberList )

           {

                     std::cout << i << " * 10 : ";

 

                     i *= 10;

                     std::cout << i << std::endl;

           }

 

           for( auto i : NumberList )

           {

                     std::cout << i << "  ";

           }

          

           std::cout << std::endl << std::endl;

 

 

           for( auto &i : NumberList )

           {

                     std::cout << i << " * 10 : ";

 

                     i *= 10;

                     std::cout << i << std::endl;

           }

 

           for( auto i : NumberList )

           {

                     std::cout << i << "  ";

           }

 

           std::cout << std::endl;

 

           return 0;

}

 

< 실행 결과 >




저작자 표시
신고
by 흥배 2012.09.26 01:07

너무 당연한 것이지만 range base for에는 배열 뿐만이 아닌 STL의 컨테이너들도 사용할 수 있습니다.

아래 예제를 통해서 STL 컨테이너를 range base for문에서 어떻게 사용하는지 보겠습니다.

 

< 예제. 2 >

#include <iostream>

#include <vector>

#include <unordered_map>

#include <string>

 

int main()

{

           std::cout << "range base for - vector" << std::endl;

 

           std::vector<int> NumberList;

           NumberList.push_back( 1 );

           NumberList.push_back( 2 );

           NumberList.push_back( 3 );

          

           for( auto i : NumberList )

           {

                     std::cout << i << std::endl;

           }

           std::cout << std::endl;

 

 

 

           std::cout << "range base for - unordered_map" << std::endl;

 

           std::unordered_map<int, std::string> NumString;

           NumString.insert( std::make_pair<int, std::string>(1, "1") );

           NumString.insert( std::make_pair<int, std::string>(2, "2") );

           NumString.insert( std::make_pair<int, std::string>(3, "3") );

 

           for( auto i : NumString )

           {

                     std::cout << "key : " << i.first << ", value : " << i.second << std::endl;

           }

 

           std::cout << std::endl;

 

           return 0;

}

 

< 실행 결과 >


 

 

range base for문은 기본적으로 STL의 이터레이터를 지원하는 컨테이너라면 문제 없이 사용할 수 있습니다. 그러므로 프로그래머가 자신만의 컨테이너를 만든다면 STL에서 정의한 이터레이터의 기능을 구현하면 range base for 문을 사용할 수 있습니다.

 

이전에는 STL 컨테이너의 모든 요소를 반복문에서 사용할 때  for_each를 사용했는데 사용하기 위해서 준비해야 할 것이 많았는데 VC10에서 lambda 덕분에 쉬워졌습니다. 그러나 range base for 문과 비교해보면 for_each+lambda 보다는 range base for 문이 더 사용하기 편한 것을 알 수 있습니다.

 

이제 VC11부터 for 반복문은 꼭 range base for를 사용하기 바랍니다^^

저작자 표시
신고
by 흥배 2012.09.21 13:01

VC10에서 선보였던 C++11의 기능 중 강력하면서 사용하기 쉽고, 자주 사용한 기능이 아마 'auto'이지 않을까 생각합니다. 예전에 강연을 할 때 auto와 관련된 예제를 보여드리면 많은 분들이 아주 좋아하시더군요(좀 놀라기도 하시더군요^^). 어떤 분들은 딴 건 제쳐두고 이것 때문이라도 VC10을 사용해야겠다는 분들이 있었습니다.

 

이번 VC11에서도 'auto'와 같은 강력한 기능이 있습니다. 바로 'range base for' 입니다. 이것을 사용하면 반복문을 아주 쉽고, 강력하게 사용할 수 있습니다.

VC 특화 기능인 for each와 비슷하기 때문에 기존에 for each를 사용하고 있다면 이제는 range base for로 쉽게 바꾸어서 사용하면 됩니다.

 

 

예제를 통해 일반적인 for , VC for each, range base for문의 차이를 예제를 통해서 보겠습니다.

 

< 예제. 1 >

#include <iostream>

  

int main()

{

           int NumberList[5] = { 1, 2, 3, 4, 5 };

 

          

           std::cout << "일반적인 for " << std::endl;

          

           for( int i = 0; i < 5; ++i )

           {

                     std::cout << i << std::endl;

           }

 

 

           std::cout << "VC++ 특화의 for each" << std::endl;

 

           for each( int i in NumberList )

           {

                     std::cout << i << std::endl;

           }

 

 

           std::cout << "range base for " << std::endl;

 

           for( auto i : NumberList )

           {

                     std::cout << i << std::endl;

           }

 

           return 0;

}

 


< 실행 결과 >


 


<예제.1>을 보면 일반적인 for 문은

for( int i = 0; i < 5; ++i )

와 같이 시작과 종료 조건, 증가 값 이렇게 3개의 조건에 의해서 반복 됩니다.

 

그러나 range base for문은 VC만의 반복문인 for each와 비슷하게 데이터셋 변수와 이 데이터셋 요소의 타입을 선언하면 됩니다.

for( auto i : NumberList )

 

기존의 for 문에 비해서 또는 for each 보다도 간편해졌고, for each는 표준이 아닌 VC만의 기능인 것에 비해서 range base for C++ 표준 기능입니다.

 

range base for 문의 문법은 아래와 같습니다.

for ( for-range-declaration : expression ) statement

 

 

range base for 덕분에 반복문의 사용이 쉬워졌고, for 문을 사용할 때 종료 조건이 잘못되어 메모리 침범을 하는 위험도 피할 수 있게 되었습니다.

저작자 표시
신고
by 흥배 2012.08.29 09:00
| 1 |

티스토리 툴바