배열, 함수, const 표현식 등이 값이 자동으로 변환되는 현상

 

몇가지 예시를 통해 어떠한 상황에 발생되는지 알아봤다.

 

배열 타입이 함수 인자로 넘겨질때 포인터 변환되는 현상

void func1(int *p)
{
    cout << *p << endl;
    // 출력 '1'
}


int main()
{
    int arr[5] = {1,2,3,4,5};
    func1(arr);
    return 0;
}

 

즉 int arr[10]; -> int* 로 바뀐다.

 

배열을 변수에 대입할때

int arr[5] = {1,2,3,4,5};
int* p = arr;   // 배열 → 포인터로 decay

 

 

배열을 템플릿 인자로 전달할 때

template <typename T>
void foo(T t)
{
    // ...
}

int arr[5];
foo(arr);   // T는 int* 로 추론됨 (int[5] 아님)

템플릿은 배열 타입을 그대로 받지 못한다.

함수 이름을 변수에 대입할 때

void Hello(int) {}

auto p = Hello;  // Hello는 함수포인터(void(*)(int))로 decay

함수는 값으로 복사가 불가능한타입라서 이경우에도 포인터로 decay된다.

auto 선언 시 const 제거

const int x = 10;
auto y = x;   // y는 int  (const 제거됨)

auto는 값복사를 전제로 타입을 추론한다.

값을 복사할때 top-level const는 의미가 없으므로 const는 제거된다.

Decay 주의점

Decay는 자동으로 타입이 단순화되는 과정이지만, 주의해야할 것들이 있다.

 

배열 크기 정보 삭제

void PrintSize(int arr[])   // 사실 int* arr
{
    cout << sizeof(arr); // 8byte (포인터 크기)
}

 

특징은, 포인터로 넘어오기 때문에 배열의 크기 정보는 사라진다.

sizeof는 배열에 크기가 아닌 포인터 크기를 반환한다.

 

오버로드

void process(int* p) { }
void process(int arr[5]) { }   // 사실 동일한 시그니처!

int a[5];
process(a); // 둘 다 int* 로 취급됨

 

Vector에 배열 Push 과정

std::vector<int*> v;
int arr[3];
v.push_back(arr);   // arr → int* decay됨

 

배열을 return하려고 할때

int arr[3];
return arr;    // int* 로 반환

+) arr은 지역변수라, 객체가 사라질때 댕글링 포인터

+ Recent posts