Delphi自指针的使用

发布于 2024-09-25 14:22:39 字数 924 浏览 8 评论 0原文

我需要在该实例中获取指向我的类实例的指针。我不能直接使用“Self”,我需要存储指针以供将来使用。我尝试了下一个代码:

type
    TTest = class(TObject)
    public
        class function getClassPointer: Pointer;
        function getSelfPointer: Pointer;
    end;

class function TTest.getClassPointer: Pointer;
begin
    Result := Pointer(Self);
end;

function TTest.getSelfPointer: Pointer;
begin
    Result := Pointer(Self);
end;

两个结果都是错误的 - 此代码:

test := TTest.Create;
Writeln('Actual object address: ', IntToHex(Integer(@test), 8));
Writeln('Class "Self" value: ', IntToHex(Integer(test.getClassPointer()), 8));
Writeln('Object "Self" value: ', IntToHex(Integer(test.getSelfPointer()), 8));

返回:

Actual object address:    00416E6C
Class "Self" value:       0040E55C
Object "Self" value:      01EE0D10

请帮助我理解,这个“自我”值是什么? “Self”是指向此类实例的指针吗?如何使用这个指针来将来在这个对象之外使用?如何从这个值得到正确的指针?

I need to get pointer to my class instance inside this instance. I can't use "Self" directly, I need store pointer for future usage. I tried next code:

type
    TTest = class(TObject)
    public
        class function getClassPointer: Pointer;
        function getSelfPointer: Pointer;
    end;

class function TTest.getClassPointer: Pointer;
begin
    Result := Pointer(Self);
end;

function TTest.getSelfPointer: Pointer;
begin
    Result := Pointer(Self);
end;

And both result are wrong - this code:

test := TTest.Create;
Writeln('Actual object address: ', IntToHex(Integer(@test), 8));
Writeln('Class "Self" value: ', IntToHex(Integer(test.getClassPointer()), 8));
Writeln('Object "Self" value: ', IntToHex(Integer(test.getSelfPointer()), 8));

returns:

Actual object address:    00416E6C
Class "Self" value:       0040E55C
Object "Self" value:      01EE0D10

Please, help me understand, what is this "Self" value ? Is "Self" a pointer to this class instance ? How use this pointer to future use outside of this object ? How get proper pointer from this value ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

回梦 2024-10-02 14:22:39

您正在尝试比较三个完全不同的实体。

@test 返回变量 test 的地址,而不是它指向的对象实例。

test.getClassPointer() 返回类元数据的地址,这是编译器生成的常量数据结构,运行时可以在其中找到虚拟方法表、运行时类型信息表等。类的所有实例共享相同的类元数据结构。指向类元数据的指针是对象实例的类型标识 - 这是对象在运行时知道它是什么类型的方式。

test.getSelfPointer() 为您提供内存中对象实例的实际地址。两个对象实例(单独创建)将具有不同的实例地址。 test.getSelfPointer() 将等于测试实例变量的内容:Pointer(test)

例如(伪代码,未测试):

type TTest = class
     end;

var test1: TTest;
    test2: TTest;

begin
  test1 = TTest.Create;  // allocates memory from the global heap, stores pointer
  test2 = test1;         // copies the pointer to the object into test2 variable
  writeln("Test1 variable points to: ", IntToHex(Integer(Pointer(test1))));
  writeln("Test2 variable points to: ", IntToHex(Integer(Pointer(test1))));
end.

You're trying to compare three completely different entities.

@test returns the address of the variable test, not the object instance that it points to.

test.getClassPointer() returns the address of the class metadata, a constant data structure generated by the compiler where the runtime can find the virtual method table, runtime type info tables, and more. All instances of a class share the same class metadata structure. The pointer to the class metadata is the object instance's type identity - it's how the object knows what type it is at runtime.

test.getSelfPointer() gives you the actual address of the object instance in memory. Two object instances (created separately) will have different instance addresses. test.getSelfPointer() will be equal to the contents of the test instance variable: Pointer(test)

For example (pseudocode, not tested):

type TTest = class
     end;

var test1: TTest;
    test2: TTest;

begin
  test1 = TTest.Create;  // allocates memory from the global heap, stores pointer
  test2 = test1;         // copies the pointer to the object into test2 variable
  writeln("Test1 variable points to: ", IntToHex(Integer(Pointer(test1))));
  writeln("Test2 variable points to: ", IntToHex(Integer(Pointer(test1))));
end.
嗼ふ静 2024-10-02 14:22:39

在您的代码片段中 test 已经是对真实实例的引用,因此您应该尝试

Writeln('Actual object address: ', IntToHex(Integer(Pointer(test)), 8));

并且您可能不需要任何 getSelfPointer 方法。如果您想要对 test 已引用的对象实例进行第二次引用,请编写:

var
  SecondReferenceToTest: TTest;
SecondReferenceToTest := test;

要查看此内容,请尝试以下操作:

type
  TTest = class(TObject)
  public
    Name: string;
  end;

procedure TestProc;
var
  test, SecondReferenceToTest: TTest;
begin
  test := TTest.Create;
  try
    test.Name := 'Named via "test" reference';
    SecondReferenceToTest := test;
    ShowMessage(SecondReferenceToTest.Name);
  finally
    test.Free;
  end;
end;

In your code fragment test already is a reference to the real instance, so you should try

Writeln('Actual object address: ', IntToHex(Integer(Pointer(test)), 8));

And you probably don't need any getSelfPointer method. If you want a second reference to the object instance that test already references, write:

var
  SecondReferenceToTest: TTest;
SecondReferenceToTest := test;

To see this, try something like:

type
  TTest = class(TObject)
  public
    Name: string;
  end;

procedure TestProc;
var
  test, SecondReferenceToTest: TTest;
begin
  test := TTest.Create;
  try
    test.Name := 'Named via "test" reference';
    SecondReferenceToTest := test;
    ShowMessage(SecondReferenceToTest.Name);
  finally
    test.Free;
  end;
end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文