Delphi 如何在不分配内存的情况下构造对象?

Delphi 如何在不分配内存的情况下构造对象?,delphi,Delphi,我希望包含在其他对象中的对象不必分配内存。例如,在Delphi中,我可以这样写: 类型 TTest=类 对象J1:tobject1; 对象J2:对象2; 构造函数创建; 毁灭者毁灭;推翻 结束; 构造函数test.Create; 开始 继承; obj1:=tobject1.创建; obj2:=tobject2.Create; 结束; 析构函数t测试Destroy; 开始 obj1.自由; obj2.自由; 继承; 结束; 类似的C++代码看起来是这样的: class测试{ tobject1-o

我希望包含在其他对象中的对象不必分配内存。例如,在Delphi中,我可以这样写:

类型
TTest=类
对象J1:tobject1;
对象J2:对象2;
构造函数创建;
毁灭者毁灭;推翻
结束;
构造函数test.Create;
开始
继承;
obj1:=tobject1.创建;
obj2:=tobject2.Create;
结束;
析构函数t测试Destroy;
开始
obj1.自由;
obj2.自由;
继承;
结束;

类似的C++代码看起来是这样的:

class测试{
tobject1-obj1;
tobject2-obj2;
};
我想重点讨论的是,在Delphi版本中,有3个内存分配,而C++版本中只有1个内存分配。在Delphi中,只有一个内存分配方法才能完成完整对象及其子对象,就像它在C++ +

中一样吗?

<强> Update <强>:完全C++测试代码:

class-tobject1{public:int-aaa;};
类tobject2{public:int-bbb;};
类测试{
tobject1-obj1;
tobject2-obj2;
公众:
void doThing(){obj1.aaa=obj2.bbb;};
};
int main()
{
{TTest*test=new-TTest;test->doThing();delete-test;}
{TTest test;test.doThing();}
返回0;
}
反汇编代码:

{TTest * test = new TTest; test->doThing(); delete test; }
013D182E  push        8  
013D1830  call        operator new (013D1299h)  
013D1835  add         esp,4  
013D1838  mov         dword ptr [ebp-0E4h],eax  
013D183E  mov         eax,dword ptr [ebp-0E4h]  
013D1844  mov         dword ptr [ebp-8],eax  
013D1847  mov         ecx,dword ptr [ebp-8]  
013D184A  call        TTest::doThing (013D133Eh)  
013D184F  mov         eax,dword ptr [ebp-8]  
013D1852  mov         dword ptr [ebp-0F0h],eax  
013D1858  push        8  
013D185A  mov         ecx,dword ptr [ebp-0F0h]  
013D1860  push        ecx  
013D1861  call        operator delete (013D104Bh)  
013D1866  add         esp,8  
{TTest test; test.doThing(); }
013D1869  lea         ecx,[ebp-18h]  
013D186C  call        TTest::doThing (013D133Eh)  
<> C++对象只需要1个内存分配来分配包含子对象的新对象,如果对象被放置在堆栈而不是堆上,甚至0个内存分配。 更新:完整的Delphi测试代码:

程序项目1;
类型
tobject1=类
aaa:长型;
结束;
tobject2=类
bbb:长型;
结束;
TTest=类
对象J1:tobject1;
对象J2:对象2;
构造函数创建;
毁灭者毁灭;推翻
程序打点;
结束;
构造函数test.Create;
开始
继承;
obj1:=tobject1.创建;
obj2:=tobject2.Create;
结束;
析构函数t测试Destroy;
开始
obj1.自由;
obj2.自由;
继承;
结束;
程序测试点;
开始
obj1.aaa:=obj2.bbb;
结束;
变量
试验:TTest;
开始
测试:=TTest.Create;
试验.打点;
免费测试;
结束。
反汇编分配代码:

Project1.dpr.35: test := TTest.Create;
0040A0F4 B201             mov dl,$01
0040A0F6 A19C924000       mov eax,[$0040929c]
0040A0FB E8DCF2FFFF       call TTest.Create
0040A100 A3F8F44000       mov [$0040f4f8],eax
Project1.dpr.36: test.doThing;
0040A105 A1F8F44000       mov eax,[$0040f4f8]
0040A10A E865F3FFFF       call TTest.doThing
Project1.dpr.37: test.Free;
0040A10F A1F8F44000       mov eax,[$0040f4f8]
0040A114 E8DBA1FFFF       call TObject.Free
反汇编创建代码:

Project1.dpr.16: obj1 := tobject1.Create;
004093F4 B201             mov dl,$01
004093F6 A144914000       mov eax,[$00409144]
004093FB E8C4AEFFFF       call TObject.Create
00409400 8B55FC           mov edx,[ebp-$04]
00409403 894204           mov [edx+$04],eax
Project1.dpr.17: obj2 := tobject2.Create;
00409406 B201             mov dl,$01
00409408 A1F0914000       mov eax,[$004091f0]
0040940D E8B2AEFFFF       call TObject.Create
00409412 8B55FC           mov edx,[ebp-$04]
00409415 894208           mov [edx+$08],eax

对于包含2个子对象的新对象,此Delphi对象需要3个内存分配。是否可以像C++一样使用一个分配(或者即使是在堆栈上0个)使用对象而不是记录(它们不支持,因为它们不支持继承)?

这里你的想法是错误的。C++和Delphi一样,知道构造函数和析构函数,只是在C++定义中没有定义它们。 不,如果不为一个类的实例分配内存,就不能分配该实例。
Delphi和C++之间也没有区别。Delphi类中的

< P>是引用类型,因此在实例化时总是会引发堆位置。因此,使用类无法实现所需的内存布局


相反,记录是值类型。如果您将两个嵌入类型放入记录中,那么内存将按照您的意愿进行布局,并且只有一个堆分配TTest构造函数中调用
tobject1
tobject2
的默认构造函数。Delphi没有这个机制,所以你必须创建对象手册。默认构造函数和析构函数被调用子对象,但不是新的和删除,C++版本只分配一个内存块来完成整个对象的合成。我从来没有尝试过,但是你可以玩覆盖。但是,注意不是Delphi方法。另一种可能性是使用代码>记录/<代码> s,它是C++、代码、结构、代码、代码等的值类型,而Delphi < Cuth>代码>类< /Cord> ES是C++类中的引用类型。整个对象只有一个内存分配,主对象和每个子对象都调用构造函数。我希望在Delphi中有这样的行为。@Mardulu:Delphi中的类不是这样工作的。我可能不应该提及它们,但是旧的Turbo Pascal < Cord>对象< /Cord>类型更像C++类,可以用作值类型,但是它们也不是自动构造的。请注意,这些旧式的
object
类型已被弃用,不再完全受支持。我想你的第一段意思是“不能”?我希望它能像你的第二段那样,但也能使用嵌入类型的继承,但如果不行的话,那就好了。值的继承为你打开了一扇大门。是的,我更正了第一段,谢谢。您可以将类型声明为
object
,而不是
class
record
。可以在堆栈上分配<>代码>对象< /代码>,嵌套对象都将处于一个分配中,类似于C++代码。然而,
object
是为了向后兼容而提供的旧语法,
record
类型在这种情况下是首选的。几年前我上次尝试type object时,它们在freepascal中工作得很好,但在delphi中有各种错误,所以我没有想过再试一次。我会尝试一下,如果他们现在能工作,我会报告。最小的测试,但看起来像对象类型工作,但真的很奇怪。它可以继承和访问父成员,但不能重写虚拟函数,构造函数/析构函数不起作用,类函数不起作用。