为什么在我使用 free() 时对象的赋值会丢失?

Why the assignment of an object is lost when I utilize free()?

我有问题。例如,当我尝试从函数获取对象或赋值时。

//Global.-
MyObject:= TMyObject.Create();  
//Local assign.-
myObj:= MyObject;

在上述情况下,如果我尝试这样做:

//Global variable.-
MyObject:= TMyObject.Create();
MyObject.MyData:= 'Salam world';  
//Local variable.-
myObj:= MyObject;
MyObject.Free();
...
ShowMessage(myObj.MyData); //Don't show the data.-

为此显示访问冲突:

//Global variable.-
MyObject:= TMyObject.Create();
MyObject.MyData:= 'Salam world';
...
//Local variable.-
myObj:= TMyObject.Create();
myObj:= MyObject;
..
MyObject.Free();
...
ShowMessage(myObj.MyData);

我需要的是在局部变量之前释放全局变量。但是我可以在分配中保留数据的副本。

感谢您的帮助!

当您按原样执行分配时,您并不是在创建对象的副本;而是在创建对象的副本。你只是让两个变量引用同一个对象。释放该对象意味着第二个变量指向您已释放的对象。

//Global variable.-
MyObject:= TMyObject.Create();
MyObject.MyData:= 'Salam world';  

下一行没有创建对象的第二个副本。它只是让 myObj 也指向 MyObject.

//Local variable.-
myObj:= MyObject;

您可以使用以下代码自行查看:

MyObject := TMyObject.Create;
MyObject.MyData := 'Some text';
ShowMessage(MyObject.MyData);      // Shows 'Some text'

myObj := MyObject;
// Change local variable property value
myObj.MyData := 'Different text';
// Display global variable property value
ShowMessage(MyObject.MyData);     // Shows 'Different text'

这一行释放了 MyObject,这意味着 myObj 现在引用了您刚刚释放的对象,因为它仅指向 MyObject.

的内容
MyObject.Free();

如果要复制,请使用 Assign

myObj := TMyObject.Create;
myObj.Assign(MyObject);

你不能释放变量你只能free/destroy对象。

所以当你在代码中调用

MyObject.Free();

你实际上是在破坏 MyObject 变量 reference/pints 到的对象。这与您的 myObj 变量 reference/points 指向的对象相同。

而它们都指向同一个对象的原因是当你调用

myObj:= MyObject;

您只是将程序用来引用该对象的数据从 mObj 变量复制到 MyObject 变量中。

您在 Delphi/Object Pascal 中看到有两种类型的变量。引用和 Non-referenced 个变量。

Non-referenced 变量是简单的变量,例如整数。它们直接指向包含其数据的内存位置。并且它们的大小与它们指向的内存块的大小完全相同。

所有引用类、接口或字符串的变量的引用变量不同。它们不是直接指向包含对象的内存块,而是指向对该对象(实例)的特殊引用。该引用实际上包含该对象在内存中的位置以及它有多大的信息。

引用变量的主要优点是你可以有多个引用变量都引用同一个对象。当您在代码的不同部分对这些变量进行不同命名时,这尤其有用。

但它们的主要缺点是您需要有适当的机制来确保包含它们引用的对象的内存在正确的时间被释放。这就是为什么您需要调用 MyObject.FreeMyObject.Destroy 才能释放该内存。

现在,在使用高级引用的情况下,您不需要自己调用对象析构函数,因为 ARC 包含自己的机制来确定何时不再需要某个对象并可以将其释放(引用计数达到零)。

在您的问题中,您声明您希望全局变量不再指向您的对象,但仍然让您的局部变量指向该对象。

我想这可能有两个原因:

首先,您可能希望全局对象引用另一个对象,同时在局部范围内保留对旧对象的引用。为此,您只需将新对象引用分配给全局对象变量

MyGlobalObject := SomeNewObject;

MyGlobalObject := TSomeObject.Create;

很快您可能希望您的全局对象变量不再引用任何有效对象。在这种情况下你只需要将它设置为特殊的nil状态

MyGlobalObject := nil;

在任何一种情况下,请确保在更改全局对象变量之前至少有一个其他变量引用该对象。为什么?

因为如果您将指向某个对象的最后一个变量更改为指向其他对象或none,您将失去交互和释放初始对象内存的能力。在编程术语中,这种情况称为内存泄漏。