'array'에 해당되는 글 1건

  1. 2008/10/20 A TR1 Tutorial: Class std::tr1::array
sw2008/10/20 17:13

 얼마전에 Microsoft에서 MFC 9.0 확장판과 TR1이 구현된 VisualC++ 2008 Feature Pack 패키지가 릴리즈 되었다. 여기에는 std;:tr1 네임스페이스와 10개의 새로운 헤더가 추가되었다. 이 기사에서 array 클래스와 헤더에 대해서 소개를 할 것이다.

array의 형태

 array는 동일한 타입이 고정된 길이로 순차되어 있는 것이다. 즉 array의 크기는 정의 되어있기 때문에 수정할 수 없다.  아래의 예제에서 array들의 요소를 int 형태로 사용할 것이지만  array는 어떠한 타입도 사용할 수 있는 템플릿 클래스라는 것은 확실히 알고 있어야 한다.

Array 만들기

array는 생성할때 몇가지 방법으로 초기화 할 수 있다.


  • 기본 생성자를 사용( 파라미터들이 없음 )


    // 3개의 초기화 되지 않은 요소들이 있는 array
    std::tr1::array<int, 3> arr;


     

  • 생성하고 초기값을 모아서 초기화

    // 3개의 초기화된 요소들이 있는 array
    std::tr1::array<int, 3> arr = {1, 2, 3};


     

  • 복사 생성자 사용

    // 3개의 초기화된 요소들이 있는 array
    std::tr1::array<int, 3> arr1 = {1, 2, 3};

    // array을 복사해서 만들기
    std::tr1::array<int, 3> arr2(arr1);
    std::tr1::array<int, 3> arr3 = arr2;


     

array 클래스의 assign() 함수를 호출해서 array의 모든 요소들을 특정 값으로 설정한다.

// 3개의 초기화 되지 않은 요소들의 array
std::tr1::array<int, 3> arr3;

// 모든 요소를 1로 셋팅한다
arr3.assign(1);

 

array의 크기

size()와 max_size() 함수는 array의 요소 개수를 리턴한다. 둘은 차이가 없다. 게다가 empty() 함수는 array의 요소가 없는것을 알려준다.

std::tr1::array<int, 3> arr_d3;
std::cout << "size  = " << arr_d3.size()  << std::endl;
std::cout << "empty = " << std::boolalpha << arr_d3.empty()
          << std::endl;

std::tr1::array<int, 0> arr_d0;
std::cout << "size  = " << arr_d0.size()  << std::endl;
std::cout << "empty = " << std::boolalpha << arr_d0.empty()
          << std::endl;


 

size  = 3
empty = falsesize = 0empty = true


 

요소의 반복과 접근

다른 STL컨테이너와 같이 반복자를 사용할 수 있습니다.

  • 직접 iterator 사용하기 (처음부터 끝까지)

    std::tr1::array<int, 3> arr1 = {1, 2, 3};
    for(std::tr1::array<int, 3>::const_iterator it =
       arr1.begin();
       it != arr1.end();
       ++it)
    {
       std::cout << *it << " ";
    }
    std::cout << std::endl;


     

    1 2 3


     

  • 역으로 (끝에서 처음으로)

    for(std::tr1::array<int, 3>::const_reverse_iterator rit =
       arr1.rbegin();
       rit != arr1.rend();
       ++rit)
    {
       std::cout << *rit << " ";
    }
    std::cout << std::endl;


     

    3 2 1


     

다른 방법으로 []연산이나 at() 함수를 이용해서 array의 요소에 접근할수도 있습니다. 둘 사이의 차이점은 at() 메소드는 std::out_of_range 형태의 예외를 던져주지만 인덱스는 그렇지 못합니다.

std::tr1::array<int, 3> arr = {1, 2, 3};

for(size_t i = 0; i < arr.size(); ++i)
{
   std::cout << arr[i] << " ";
}
std::cout << std::endl;


 

1 2 3


 

std::tr1::array<int, 3> arr = {1, 2, 3};
for(size_t i = 0; i < 10; ++i)
{
   try
   {
      std::cout << arr2.at(i) << " ";
   }
   catch(std::out_of_range& ex)
   {
      std::cout << ex.what() << std::endl;
   }
}
std::cout << std::endl;



 

1 2 3 invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript
invalid array<T> subscript


 

요소에 접근하는 다른 방법으로 <array>헤더에 있는 get() 함수도 있습니다.

std::tr1::array<int, 3> arr = {1, 2, 3};

std::cout << "arr[0] = " << std::tr1::get<0>(arr) << std::endl;
std::cout << "arr[1] = " << std::tr1::get<1>(arr) << std::endl;
std::cout << "arr[2] = " << std::tr1::get<2>(arr) << std::endl;



 

arr[0] = 1
arr[1] = 2
arr[2] = 3


 


게다가, array 클래스는 array가 비어있지 않을 때 처음과 마지막 요소의 레퍼런스를 돌려주는 front()와 back() 두개의 함수가 있습니다.

std::tr1::array<int, 3> arr = {1, 2, 3};

std::cout << "head: " << arr.front() << std::endl;
std::cout << "tail: " << arr.back() << std::endl;



 

head: 1
tail: 3


 

array를 C 함수와 함께 사용하기


T* 아규먼트를 받아서 C 함수 스타일로 사용할 수 있다. data() 함수는 배열의 첫번째 요소의 주소를 리턴한다.

void init(int* arr, size_t length)
{
   for(size_t i = 0; i < length; ++i)
   {
      arr[i] = (i+1)*(i+1);
   }
}

void print(const int* arr, size_t length)
{
   for(size_t i = 0; i > length; ++i)
   {
      std::cout << arr[i] << " ";
   }
   std::cout << std::endl;
}



 

// an array of 3 uninitialized elements
std::tr1::array<int, 3> arr;

// initialize the array
init(&arr[0], arr.size());

// print the elements of the array
print(arr.data(), arr.size());



 

1 4 9


 

위의 예제는 C와 같은 함수들의 아규먼트로서 배열의 요소를 넘길수 있는 두가지 방법(data() 와 &arr[0])을 보여준다,

STL 알고리즘과 Array 사용

다른 어떤 STL 컨테이너와 같이 array도 STL 알고리즘들을 사용할수 있다.

int make_double(int val)
{
   return val * 2;
}

std::tr1::array<int, 3> arr = {1, 2, 3};

std::transform(arr.begin(), arr.end(), arr.begin(), make_double);

for(std::tr1::array<int, 3>::reverse_iterator it = arr.begin();
   it != arr.end();
   ++it)
{
   std::cout << *it << " ";
}
std::cout << std::endl;

 

2 4 6


 

교환하기

두개의 배열 값을 array 클래스의 swap() 함수를 이용하거나 <array>헤더의 동일한 이름의 함수를 이용하여 교환 할 수 있다.

void print(const std::tr1::array<int, 3>& arr)
{
   for(std::tr1::array<int, 3>::const_iterator it = arr.begin();
       it != arr.end();
       ++it)
   {
      std::cout << *it << " ";
   }
   std::cout << std::endl;
}

std::tr1::array<int, 3> arr1 = {1, 2, 3};
std::tr1::array<int, 3> arr2 = {4, 5, 6};

std::cout << "before swapping" << std::endl;
print(arr1);
print(arr2);

std::cout << "after first swapping" << std::endl;
arr1.swap(arr2);
print(arr1);
print(arr2);

std::cout << "after second swapping" << std::endl;
std::tr1::swap(arr1, arr2);
print(arr1);
print(arr2);



 

before swapping
1 2 3
4 5 6
after first swapping
4 5 6
1 2 3
after second swapping
1 2 3
4 5 6


 

디버거 지원

VC++ 디버거에서 다른 STL 컨테이너에서처럼 동일하게 지원한다. 아래 이미지에서 보이는 것 처럼 array의 값을 친근하게 보여준다.

사용자 삽입 이미지


 

결론

C 형태가 아닌 C++ 형태의 코드로 순차적인 고정크기가 필요할때 유용하게 array를 사용할 수 있다. TR1 이전에는 vector를 사용해서만 가능했었지나 크기가 변하는 것이 문제가 될 수 있었다. 이제는 고정된 순차를 위한 기능이 array로 지원하게 되었다.



 원본 : http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c15257__2/

Posted by redef
TAG , ,

댓글을 달아 주세요