Вопрос

Этот код в приложении с графическим интерфейсом компилируется и запускается:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Self := TForm1.Create(Owner);
end;

(протестировано с Delphi 6 и 2009)

  • почему доступна для самостоятельной записи, а не только для чтения?
  • в каких ситуациях это могло бы быть полезно?

Редактировать:

  • возможно ли это также в Delphi Prism?(Я думаю, да, это так, понимаете здесь)

Обновить:Приложения / библиотеки Delphi, которые используют самоназначение:

Это было полезно?

Решение

Это не так плохо, как могло бы быть.Я только что протестировал его в Delphi 2009, и казалось бы, что, хотя параметр Self не использует константа семантика, на которую вы, кажется, намекаете, что она должна, также не используется var семантика, так что вы можете изменять ее сколько угодно в своем методе, фактически не теряя ссылку, которую вызывающий объект хранит на ваш объект.Это было бы очень плохо.

Что касается причины, почему, то один из двух ответов.Либо простая оплошность, либо то, что предложил Марко:чтобы позволить вам передать Себя в var параметр.

Другие советы

Может быть, разрешить передачу параметров const или var?

Это может быть артефакт, поскольку system нигде не имеет self слева от знака := .

Присвоение себе настолько нелогично и бесполезно, что эта "функция", вероятно, является упущением.И, как и в случае с присваиваемыми константами, исправить такие проблемы не всегда легко.

Простой совет здесь заключается в следующем:не делай этого.

На самом деле, "Self" - это просто ссылка на имя места в стеке, в котором хранится адрес, указывающий на объект в куче.Принудительное использование этой переменной только для чтения возможно, по-видимому, разработчик решил этого не делать.Я считаю, что это решение является произвольным.

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

Обновленный: В ответ на PatrickvL Комментарий

"Переменной" "Self" нет в стеке (насколько мне известно, ее никогда не бывает);Вместо этого это значение помещается в регистр (EAX, если быть точным) непосредственно перед выполняется вызов любого метода объекта.–

Нет, у Self есть фактический адрес в памяти.Попробуйте этот код, чтобы убедиться в этом сами.

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(IntToStr(Integer(@Self)));
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  newform: TForm;
  p: ^Integer;
begin
  Self.Caption := 'TheOriginal';
  newform := TForm.Create(nil);
  try
    newform.Caption := 'TheNewOne';
    // The following two lines is, technically, the same as
    //   Self := newform;
    p := Pointer(@Self);
    p^ := Integer(newform);
    ShowMessage(Self.Caption);  // This will show 'TheNewOne' instead of 'TheOriginal'
  finally
    Self.Free; // Relax, this will free TheNewOne rather than TheOriginal
  end;
end;

Иногда, когда вы хотите оптимизировать метод настолько, насколько это возможно (не прибегая к сборке), 'Self' можно (ab) использовать как 'свободную' переменную - это может просто означать разницу между использованием стека и использованием регистров.

Конечно, содержимое стека, скорее всего, уже присутствует в кэше процессора, поэтому доступ к нему должен быть быстрым, но регистры работают еще быстрее.

В качестве дополнительной заметки :Я все еще скучаю по тем временам, когда я программировал на Motorola 68000 от Amiga и мог позволить себе роскошь 16 регистров данных и 16 адресных регистров....Я не могу поверить, что мир решил использовать ограниченные 4 регистра линейки процессоров 80x86!

И в качестве последнего замечания, я иногда предпочитаю использовать Self, поскольку оптимизатор Delphi, ну, не оптимизация что ж, на самом деле.(По крайней мере, это бледнеет по сравнению с тем, какие хитрости можно найти, например, в различных оптимизаторах LLVM.) ИМХО, и YMMV, конечно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top