상수 매개변수
상수 매개변수 (Constant parameters)
매개변수 안의 내용을 루틴이 바꾸지 않는다는 것을 컴파일러에게 알려주고 싶을 때가 있어요. 그럴 때 쓰는 것이 **상수 매개변수(constant parameter)**예요. const로 선언하면 컴파일러가 최적화를 하거나 안전 검사를 수행할 수 있어요.
본문
변수 매개변수와 값 매개변수 외에도 Free Pascal은 상수 매개변수를 지원해요. 상수 매개변수는 다음과 같이 선언해요.
procedure 이름(const 매개변수 : 타입);
매개변수를 const로 지정하는 것은 컴파일러에게 "이 매개변수의 내용은 호출된 루틴에 의해 바뀌지 않을 것"이라는 힌트를 주는 거예요. 이 덕분에 컴파일러는 그렇지 않았다면 할 수 없었던 최적화를 수행할 수 있고, 루틴 내부의 코드에 대해 어떤 검사도 수행할 수 있어요. 구체적으로, 매개변수에 대한 대입을 금지할 수 있고, const 매개변수를 변수 매개변수를 요구하는 다른 함수에 넘길 수 없도록 컴파일러가 검사할 수도 있어요. 주된 용도는 스택 크기를 줄여 성능을 향상시키면서도, 값 전달(pass by value)의 의미를 유지하는 거예요.
참고: Delphi와 달리, const 매개변수가 어떻게 기본(underlying) 루틴에 전달되는지에 대해 가정을 세우면 안 돼요. 특히 "큰 크기의 매개변수는 참조로 전달된다"는 가정은 올바르지 않아요. 그런 용도에는 컴파일러 버전 2.5.1부터 사용 가능한 constref 매개변수 타입을 써야 해요.
예외가 하나 있어요. stdcall 호출 규약에서는 COM 표준과의 호환을 위해 큰 const 매개변수가 참조로 전달돼요.
참고: const를 지정하는 것은 프로그래머와 컴파일러 사이의 계약이에요. 루틴이 실행될 때 const 매개변수의 내용이 바뀌지 않을 것이라고 컴파일러에게 말하는 쪽은 프로그래머이지, 매개변수가 바뀌지 않을 것이라고 프로그래머에게 말하는 쪽은 컴파일러가 아니에요.
이것은 특히 참조 카운트 타입(refcounted type)을 쓸 때 중요하고 눈에 띄어요. 그런 타입에서는 const를 쓰면 보이지 않는 참조 카운트 증가/감소가 생략돼요. 그 덕분에 컴파일러가 이런 루틴의 보이지 않는 try/finally 프레임을 생략할 수 있는 경우가 많아요.
부작용으로, 다음 코드는 기대한 출력을 만들어내지 못해요.
Var
S : String = 'Something';
Procedure DoIt(Const T : String);
begin
S:='Something else';
Writeln(T);
end;
begin
DoIt(S);
end.
이 코드는 다음과 같이 출력해요.
Something else
이 동작은 의도된 것이에요. T가 const로 선언됐기 때문에 참조 카운트 조작이 생략되고, 결과적으로 S의 새 값이 그대로 보이는 거예요.
상수 매개변수도 타입 없이(untyped) 선언할 수 있어요. 타입 없는 매개변수에 대한 자세한 내용은 14.4.2절(752페이지)에서 다뤄요.
값 매개변수처럼, 상수 매개변수도 기본값을 가질 수 있어요.
개방 배열(open array)도 상수 매개변수로 전달할 수 있어요. 자세한 내용은 14.4.5절(759페이지)에서 다뤄요.
더 알아보기
- 값 매개변수(14.4.1)와 변수 매개변수(14.4.2), 그리고
constref를 함께 비교해 보면 좋아요. - 참조 카운트 타입의 내부 동작은 14.4.8에서 자세히 다뤄요.