Переменные delphi инициализируются значением по умолчанию?

88

Я новичок в 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? Например, мне интересно, может ли это зависеть от настройки компилятора или, возможно, работать по-разному на разных машинах. Нормально ли полагаться на инициализированные значения по умолчанию для объектов или вы явно задаете все переменные экземпляра в конструкторе?

Что касается переменных стека (уровня на уровне процедуры), мои тесты показывают, что unitialized booleans истинны, а целые числа счисления - 2129993264, а неинициализированные объекты - это просто недопустимые указатели (т.е. не ноль). Я предполагаю, что норма должна всегда устанавливать переменные уровня процедуры перед их доступом?

  • 2
    Два примечания: 1. Записи не инициализируются. 2. Перечисленные ссылочные переменные всегда инициализируются. !НО! в функции, которая возвращает строку, 'Result' не инициализируется пустой строкой, как вы можете ожидать. Это потому, что «Результат» не является локальной переменной. Поэтому всегда делайте: Result: = '';
  • 0
    также смотрите: Какие переменные инициализируются, когда в Delphi?
Теги:
variables
initialization

9 ответов

94
Лучший ответ

Да, это документированное поведение:

  • Поля объекта всегда инициализируются 0, 0.0, '', False, ноль или что-то еще.

  • Глобальные переменные всегда инициализируются также 0 и т.д.

  • Локальные подсчетные переменные всегда инициализируются нулем или ';;

  • Локальные переменные, не содержащие ссылки, не инициализированы, поэтому вы должны назначить значение, прежде чем сможете их использовать.

Я помню, что Барри Келли где-то написал определение для "reference-counted", но больше не может его найти, поэтому это должно сделать в то же время:

reference-counted ==, которые подсчитываются сами по себе, или прямо или косвенно содержат поля (для записей) или элементы (для массивы), которые подсчитываются как: string, variant, interfaceили динамический массив или статический массив, содержащий такие типы.

Примечания:

  • record сам по себе недостаточно, чтобы засчитываться
  • Я еще не пробовал это с дженериками.
  • 2
    Как отметил Джакомо в комментариях ниже, все это объясняется в файлах справки Delphi по адресу ms-help: //borland.bds4/bds4ref/html/Variables.htm. В Delphi 2009 я нашел ту же информацию, выполнив поиск по справке по «переменным» (как ни странно, я пробовал много поисков, но не думал, что попробую тот).
  • 8
    Локальные переменные инициализируются ($ 0), если они имеют управляемый тип, такой как строки, интерфейсы, динамические массивы или варианты
Показать ещё 6 комментариев
27

Глобальные переменные, не имеющие явного инициализатора, выделяются в разделе BSS в исполняемом файле. Они фактически не занимают места в EXE; раздел BSS - это специальный раздел, который ОС выделяет и очищает до нуля. В других операционных системах существуют аналогичные механизмы.

Вы можете зависеть от глобальных переменных, инициализированных нулями.

18

Поля класса по умолчанию равны нулю. Это документировано, поэтому вы можете положиться на него. Локальные varayables стека undefined, если строка или интерфейс не установлены равными нулю.

  • 0
    Благодарю. "Ноль" меня немного смущает - значит ли это, что строки - это '', а интерфейсы - ноль?
  • 4
    Да, именно так. nil = 0 (на уровне ассемблера) и '' = nil (соглашение Delphi).
Показать ещё 1 комментарий
16

Как примечание к стороне (поскольку вы новичок в Delphi): глобальные переменные могут быть инициализированы непосредственно при их объявлении:

var myGlobal:integer=99;
  • 1
    Так как 10.3 то же самое относится к локальным переменным
8

Здесь цитата из Ray Lischners Delphi в двух словах Глава 2

"Когда Delphi сначала создает объект, все поля начинаются пустым, то есть указатели инициализируются на нуль, строки и динамические массивы пусты, числа имеют нулевое значение, логические поля - False, а варианты заданы к Неназначенному (подробности см. в NewInstance и InitInstance в Главе 5.)"

Верно, что переменные local-in-scope должны быть инициализированы... Я бы рассмотрел вышеприведенный комментарий, что "Глобальные переменные инициализируются" как сомнительные до тех пор, пока не будет предоставлена ​​ссылка - я не верю в это.

редактировать... Барри Келли говорит, что вы можете полагаться на то, что они ноль-инициализированы, и поскольку он в команде разработчиков Delphi, я считаю, что стоит:) Спасибо Барри.

  • 0
    В справке delphi 2006 вы можете найти ее здесь: ms-help: //borland.bds4/bds4ref/html/Variables.htm "Если вы не инициализируете глобальную переменную явно, компилятор инициализирует ее как 0. Данные экземпляра объекта ( поля) также обнуляются ".
4

Из файла справки Delphi 2007:

мс-помощь://borland.bds5/devcommon/variables_xml.html

"Если вы явно не инициализируете глобальную переменную, компилятор инициализирует ее до 0.

4

Глобальные переменные и данные экземпляра объекта (поля) всегда инициализируются до нуля. Локальные переменные в процедурах и методах не инициализируются в Win32 Delphi; их содержание undefined, пока вы не присвоите им значение в коде.

3

У меня есть одна маленькая проблема с ответами. Delphi заносит в память пространство памяти глобалов и вновь созданных объектов. Хотя это NORMALLY означает, что они инициализированы, есть один случай, когда они не являются: перечислены типы со специфическими значениями. Что, если ноль не является юридическим значением?

  • 1
    Ноль - это всегда допустимые значения, это 1-е значение перечисления. Вы можете увидеть это с помощью ord (MyFirstEnumValue).
  • 0
    Будет возвращено первое значение в перечисляемом типе.
Показать ещё 2 комментария
2

Даже если язык предлагает инициализацию по умолчанию, я не верю, что вы должны полагаться на них. Инициализация значения делает его более понятным для других разработчиков, которые могут не знать о инициализации по умолчанию в языке и предотвращают проблемы между компиляторами.

  • 3
    Конечно вы можете. И ты должен. Инициализация всего в 0 / '' / false / nil в каждом конструкторе просто не нужна. Инициализация глобальных переменных, с другой стороны, не так уж глупа - я никогда не смогу вспомнить, инициализированы они или нет (так как я их не часто использую).
  • 1
    Если Delphi позволит вам инициализировать переменную в той же точке, в которой вы ее объявили (например, var fObject: TObject = nil), я был бы склонен согласиться с тем, что инициализация значения, вероятно, является хорошей идеей. Но мне кажется, что сделать это в конструкторе для каждого поля объекта немного сложнее.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню