델파이 변수는 기본적으로 값으로 초기화됩니까?


103

저는 Delphi를 처음 접했고 기본적으로 어떤 개체 변수와 스택 변수가 초기화되는지 확인하기 위해 몇 가지 테스트를 실행했습니다.

TInstanceVariables = class
  fBoolean: boolean; // always starts off as false
  fInteger: integer; // always starts off as zero
  fObject: TObject; // always starts off as nil
end;

이것은 내가 다른 언어에서 익숙한 행동이지만 Delphi에서 의존하는 것이 안전한지 궁금합니다. 예를 들어 컴파일러 설정에 따라 달라지는 지 아니면 다른 컴퓨터에서 다르게 작동하는지 궁금합니다. 객체의 기본 초기화 값에 의존하는 것이 정상입니까, 아니면 생성자에서 모든 인스턴스 변수를 명시 적으로 설정합니까?

스택 (프로 시저 수준) 변수의 경우, 내 테스트에서 단위 화 된 부울이 참이고 단위 화 된 정수가 2129993264이며 초기화되지 않은 객체는 잘못된 포인터 (즉 nil이 아님)임을 보여줍니다. 나는 그것들에 접근하기 전에 항상 프로 시저 수준의 변수를 설정하는 것이 규범이라고 생각한다.


3
두 가지 참고 : 1. 레코드가 초기화되지 않습니다. 2. 참조 카운트 변수는 항상 초기화됩니다. !그러나! 문자열을 반환하는 함수에서 '결과'는 예상대로 빈 문자열로 초기화되지 않습니다. 이는 '결과'가 로컬 변수가 아니기 때문입니다. 따라서 항상 다음을 수행하십시오. 결과 : = '';
InTheNameOfScience


이것이 귀하의 질문에 대답합니까? Delphi에서는 어떤 변수가 초기화됩니까?
InTheNameOfScience

답변:


105

예, 이것은 문서화 된 동작입니다.

  • 개체 필드는 항상 0, 0.0, '', False, nil 또는 적용되는 항목으로 초기화됩니다.

  • 전역 변수는 항상 0 등으로 초기화됩니다.

  • 로컬 참조 카운트 * 변수는 항상 nil 또는 ''로 초기화됩니다.

  • 참조 횟수가 계산되지 않은 지역 * 변수는 초기화되지 않으므로 사용하기 전에 값을 할당해야합니다.

나는 기억 배리 켈리 곳은 "참조 - 계산"에 대한 정의를 썼다, 그러나 이것은 그 동안 무엇을해야하므로, 더 이상 그것을 찾을 수 없습니다 :

reference-counted == 자체적으로 참조 계산되거나 직접 또는 간접적으로 필드 (레코드의 경우) 또는 참조 계산되는 요소 (배열의 경우)를 포함합니다. string, variant, interface 또는 동적 배열 또는 이러한 유형을 포함하는 정적 배열 .

노트:

  • record 그 자체로는 참조 계산에 충분하지 않습니다.
  • 나는 아직 제네릭으로 이것을 시도하지 않았습니다.

2
Giacomo가 아래 주석에서 지적했듯이, 이것은 모두 ms-help : //borland.bds4/bds4ref/html/Variables.htm의 Delphi 도움말 파일에 설명되어 있습니다. Delphi 2009에서 "변수"에 대한 도움말을 검색하여 동일한 정보를 찾았습니다 (재밌게도 많은 검색을 시도했지만 시도해 볼 생각은 없었습니다).
MB.

8
지역 변수는 문자열, 인터페이스, 동적 배열 또는 변형과 같은 관리 유형 인 경우 초기화됩니다 ($ 0)
Francesca

5
하지만 예외가 있습니다! 생성자를 재정의하고 상속 된 생성자를 호출하지 않으면 일부 필드가 초기화되지 않을 가능성이 있습니다! (특히 이전 Delphi 버전에서 그렇습니다.) TObject.Create는 모든 데이터를 제로화하는 역할을하므로이를 호출하지 않으면 알 수없는 데이터가 발생할 수 있습니다.
Wim ten Brink

18
@WimtenBrink 나는 당신이 틀렸다고 생각합니다. 초기화는 TObject.Createvoid 메서드 내 에서 수행되지 않지만 class function TObject.InitInstance(Instance: Pointer): TObject;이전 Delphi 버전의 경우에도 생성자 호출 전에 항상 호출됩니다. 귀하의 의견은 IMHO 잘못되고 혼란 스럽습니다.
Arnaud Bouchez

7
문자열을 반환하는 함수에서 '결과'는 예상대로 빈 문자열로 초기화되지 않는다는 것을 잊지 마십시오. 이는 '결과'가 로컬 변수가 아니기 때문입니다.
InTheNameOfScience

27

명시 적 이니셜 라이저가없는 전역 변수는 실행 파일의 BSS 섹션에 할당됩니다. 그들은 실제로 EXE에서 어떤 공간도 차지하지 않습니다. BSS 섹션은 OS가 할당하고 0으로 지우는 특수 섹션입니다. 다른 운영 체제에도 유사한 메커니즘이 있습니다.

0으로 초기화되는 전역 변수에 의존 할 수 있습니다.


21

클래스 필드는 기본적으로 0입니다. 이것은 신뢰할 수 있도록 문서화되어 있습니다. 로컬 스택 변수는 문자열 또는 인터페이스가 아니면 정의되지 않으며 0으로 설정됩니다.


감사. "제로"는 약간 혼란 스럽습니다. 즉, 문자열은 ''이고 인터페이스는 nil입니까?
MB.

4
예, 정확히 그렇습니다. nil = 0 (어셈블러 수준) 및 ''= nil (델파이 규칙).
gabr

1
"문자열이나 인터페이스가 아닌 경우"는 현실에 대한 완전한 설명이 아닙니다. 예를 들어 동적 배열도 초기화됩니다. 보다 일반적으로 규칙은 관리되는 (참조 카운트) 유형의 변수가 로컬 인 경우에도 초기화된다는 것입니다.
안드레아스 Rejbrand


7

다음은 Ray Lischners Delphi가 요약 한 2 장 에서 인용 한 것입니다.

"Delphi가 객체를 처음 생성 할 때 모든 필드가 비어있는 상태로 시작합니다. 즉, 포인터가 nil로 초기화되고, 문자열과 동적 배열이 비어 있고, 숫자 값이 0이고, 부울 필드가 False이고, Variants가 할당되지 않음으로 설정됩니다. (자세한 내용은 5 장의 NewInstance 및 InitInstance를 참조하십시오.) "

범위 내 변수를 초기화해야한다는 것은 사실입니다. 위의 "글로벌 변수가 초기화되었습니다"라는 주석은 참조가 제공 될 때까지 모호한 것으로 취급 할 것입니다. 믿지 않습니다.

편집 ... Barry Kelly는 그것들이 0으로 초기화되는 것에 의존 할 수 있다고 말합니다. 그리고 그가 Delphi 컴파일러 팀에 있기 때문에 나는 그것이 의미한다고 믿습니다. :) Barry 감사합니다.


1
델파이 2006 도움말에서 다음 위치에서 찾을 수 있습니다. ms-help : //borland.bds4/bds4ref/html/Variables.htm "전역 변수를 명시 적으로 초기화하지 않으면 컴파일러가이를 0으로 초기화합니다. 개체 인스턴스 데이터 ( 필드)도 0으로 초기화됩니다. "
Giacomo Degli Esposti

"나는 믿지 않는다"때문에 반대표를 던졌습니다. 이것은 종교가 아니라 프로그래밍입니다. 그리고 Giacomo는 방금 진실을 보여주었습니다.
InTheNameOfScience

6

전역 변수 및 개체 인스턴스 데이터 (필드)는 항상 0으로 초기화됩니다. 프로 시저 및 메서드의 로컬 변수는 Win32 Delphi에서 초기화되지 않습니다. 코드에서 값을 할당 할 때까지 해당 내용은 정의되지 않습니다.


5

언어가 기본 초기화를 제공하더라도 이에 의존해야한다고 생각하지 않습니다. 값으로 초기화하면 언어의 기본 초기화에 대해 알지 못하는 다른 개발자에게 훨씬 더 명확 해지고 컴파일러 간의 문제를 방지 할 수 있습니다.


4
물론 당신은 할 수. 그리고 당신은해야합니다. 모든 생성자에서 모든 것을 0 / ''/ false / nil로 초기화하는 것은 불필요합니다. 반면에 전역 변수를 초기화하는 것은 그렇게 어리석지 않습니다. 초기화되었는지 여부를 기억할 수 없습니다 (많이 사용하지 않기 때문에).
gabr

2
델파이가 변수를 선언하는 것과 같은 지점에서 초기화 할 수있게했다면 (예 : var fObject : TObject = nil) 값을 초기화하는 것이 아마도 좋은 생각이라는 데 동의 할 것입니다. 그러나 나에게는 모든 개체 필드의 생성자에서 수행하는 것이 약간 많은 것 같습니다.
MB.

4

Delphi 2007 도움말 파일에서 :

ms-help : //borland.bds5/devcommon/variables_xml.html

"전역 변수를 명시 적으로 초기화하지 않으면 컴파일러가이를 0으로 초기화합니다."


3

주어진 답변에 대해 약간의 불만이 있습니다. Delphi는 전역과 새로 생성 된 객체의 메모리 공간을 제로화합니다. 이 NORMALLY 는 초기화 되었음을 의미 하지만 초기화되지 않은 경우가 있습니다. 특정 값을 가진 열거 형 유형입니다. 0이 합법적 인 가치가 아니면 ??


1
0은 항상 유효한 값이며 열거 형의 첫 번째 값입니다. ord (MyFirstEnumValue)로 볼 수 있습니다.
Francesca

열거 형의 첫 번째 값을 반환합니다.
skamradt

6
열거 형에 명시 적으로 값을 할당하는 경우 0이 항상 유효한 값은 아닙니다. 이 경우 여전히 0으로 초기화되고 잘못된 값이 있습니다. 그러나 열거 형은 일반적인 정수 유형 위에 그려진 구문상의 설탕 일 뿐이므로 실제로는 아무 것도 깨뜨리지 않습니다. 코드가이를 처리 할 수 ​​있는지 확인하십시오.
Mason Wheeler

2
@ François : 다음과 같이 열거 형을 정의하지 않으면 :TOneTwoThree = (One=1, Two=2, Three=3);
fnkr

0

새로 도입 된 (Delphi 10.3 이후) 인라인 변수로 인해 초기 값을 더 쉽게 제어 할 수 있습니다.

procedure TestInlineVariable;
begin
  var index: Integer := 345;
  ShowMessage(index.ToString);
end;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.