그냥 게임개발자

fill() 본문

C++ 나만의 복습

fill()

sudoju 2024. 4. 7. 16:59

fill()

모든 값으로 초기화 할 수 있는 함수다.

0, 1, 100 등 모든 숫자로 초기화가 가능하다.

 

 

memset()

-1, 0으로만 초기화 가능

memset()을 쓰다보면 0, -1 이외의 값으로 초기화하다 틀리는 경우가 있다.

이 때 fill()을 추천한다.

 

 

여기서 보면 memset()은 0과 -1로만 초기화 가능하다보니 fill보다 시간적으로 더 빠르고 최적화 할 수 있다.

 

 

fill()

O(n)의 시간 복잡도를 가진다

fill(시작값 - first, 끝값, -last, 초기화하는 값 - val)

이런식으로 값을 초기화한다.

 

모든 값을 기반으로 초기화가 가능하며 [first, last]까지 val로 초기화한다.

 

fill()로 배열의 모든 값이 아닌 일부값을 초기화하는 경우도 있지만 보통은 전체를 초기화하는게 좋음

 

void fill(ForwardIterator first, ForwardIterator last, const T&val);

 

 

#include <iostream>
#include <algorithm>

using namespace std;

int a[10];
int b[10][10];

int main()
{
    // 이터레이터이기에 주소의 개체를 넣어줘야 함
    fill(&a[0], &a[10], 100);
    
    for (int i = 0; i < 10; ++i)
    {
        cout << a[i] << " ";
    }
    
    cout << '\n';
    
    fill (&b[0][0], &b[9][10], 2);
    for (int i = 0; i < 10; ++i)
    {
        for (int j = 0; j < 10; ++j)
        {
            cout << b[i][j] << " ";
        }
        cout << '\n';
    }
    
    return 0;
}

 

결과먼저보고 설명하는게 편해요

일단 따라해보고 결과보고 그다음에 이해하는게 더 재밌잖아요

아니라구요?

난 그래요

 

:)

 

 

    fill(&a[0], &a[10], 100);

이것은 보면 알겠지만 a[0]부터 시작해 a[9]까지 100으로 초기화한다.

두번째 인자에 &a[10]은 포함하지 않는다 이전값인 a[9]를 포함한다.

    fill (&b[0][0], &b[9][10], 2);

이 또한 마찬가지다.

근데 여기서 의문이가는 사람도 있을 것이다

왜 두번째 인자는 &b[9][10]이지?

&b[10][10]이지 않은가?

 

깡!

 

왜그러냐면 b[10][10]으로 초기화했으면 첫번째 배열은 0~9까지가 마지막이고 두번째 배열도 0~9까지니까

우리가 접근해야 할 인덱스는 결국 b[9][9]까지이다.

그러니 last라는 인자값에는 결국 마지막 주소의 +1을 넣어줘야 하니

b[9][10]이 되는거다.

 

나도 이해 안가긴했음 ㅇㅇ 처음배울때

 

그러면 이 fill을 주소로 인자를 넘겼으니 array to pointer decay를 활용해서 fill함수를 더 가독성있게 사용할 수 있다.

 

#include <iostream>
#include <algorithm>

using namespace std;

int a[10];
int b[10][10];

int main()
{
    fill(a, a + 10, 100);
    
    for (int i = 0; i < 10; ++i)
    {
        cout << a[i] << " ";
    }
    
    cout << '\n';
    
    fill(&b[0][0], &b[0][0] + 10 * 10, 2);
    for (int i = 0; i < 10; ++i)
    {
         for (int j = 0; j< 10; ++j)
         {
             cout << b[i][j] << " ";   
         }
         cout << '\n';
    }
    
    return 0;
}

 

하지만 2차원 이상일 경우에는 &b[0][0] + 숫자로 해야한다.

 

근데

왜 fill()로 전체 초기화를 해야하는가?

 

만약에 아래 코드와 같이 8 * 8의 정사각형으로 초기화를 시키고 싶어서 다음과 같이 초기화를 시켰는데 생각과 다르게 초기화가 될 수도 있다.

 

#include <iostream>
#include <algorithm>

int a[10][10];

int main()
{
    fill(&a[0][0], &a[0][0] + 8 * 8, 4);
    for (int i = 0; i < 10; ++i)
    {
        for (int j = 0; j < 10; ++j)
        {
            cout << a[i][j] << " ";
        }
        
        cout << '\n';
    }
    
    return 0;
}

 

ㅇㅇ 이렇다.

이상하게 된다.

 

보면은 fill로 초기화가 되었을 때 우리가 사용하는 2중반복문처럼 하나하나 인덱스를 접근해서 사용한다라기보단, 순차적으로 1행에 있는 요소들을 초기화한 뒤에 그 다음 2행 3행 4행 이런식으로 초기화가 일어나기 때문이다.

 

 

'C++ 나만의 복습' 카테고리의 다른 글

쓰지 말아야 할 초기화 방법 {0, }  (0) 2024.04.07
memset()  (0) 2024.04.07
이터레이터는 일반화된 포인터인가?  (0) 2024.04.07
이터레이터와 포인터의 차이  (0) 2024.04.07
이터레이터!  (0) 2024.04.07