Проблемы перегрузки операторов в Delphi

Вольный перевод поста On the operator overloading in Delphi.

Перегрузка операторов в Delphi является простой если запись не содержит в себе полей-ссылок на объекты в куче. Чтобы проиллюстрировать эту проблему рассмотрим следующий (некорректный!) пример:

Строка #59 (C:= A + B) работает следующим образом:

  • Временная запись Result помещается в стек
  • Временная запись заполняется суммой A + B (метод Adder.Add)
  • Временная запись присваивается (поверхностным копированием) переменной C
  • Временная запись убирается со стека

Код работает правильно если Adder не содержит ссылок на кучу, FRef в экземпляре Adder делает ситуацию более сложной. Вы должны всегда инициализировать поле FRef для каждого экземпляра Adder, но вы не можете финализировать временную запись которая создана на строке #59. (также не можете финализировать запись которая инициализируется в строке #58 и теряется в строке #59).

Единственный путь исправить утечку памяти — закомпостировать строку #58, но это не будет работать в более сложных случаях, например, когда переменная должна участвовать в выражении справа.

Правильное решение использует автоматическое управление памятью вместо простых указателей. Ниже решение использующее интерфейс:

Полезный побочный эффект при таком подходе в том что вам не нужно инициализировать или финализировать поле FRef вручную (но вы можете это делать). Несколько строк в процедуре Test, показанной выше, закомментированы потому, что они больше не нужны, но они могут быть раскомментированы и код продолжит верно работать — автоматическое управление памятью для интерфейсов обеспечит это.

Очень интересно знать как обсуждаемая проблема решается в C++. Стандартный C++ подход полностью отличается — он требует перегрузки оператора присваивания (возможность, которую Delphi не поддерживает) и написания конструктора копирования (другая концепция отсутствующая в Delphi). Я планирую обсудить это позже.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *