我希望其他对象中包含的对象不必分配内存。例如,在德尔福我可以这样写:如何在不分配内存的情况下构造对象?
type
TTest = class
obj1: tobject1;
obj2: tobject2;
constructor Create;
destructor Destroy; override;
end;
constructor TTest.Create;
begin
inherited;
obj1 := tobject1.Create;
obj2 := tobject2.Create;
end;
destructor TTest.Destroy;
begin
obj1.Free;
obj2.Free;
inherited;
end;
类似C++代码是这样的:
class TTest {
tobject1 obj1;
tobject2 obj2;
};
我想专注于不同的是如何在Delphi版本有3个内存分配而在C++版本中只有1个。有没有办法在德尔福只有一个内存分配一个完整的对象及其子对象,就像在C++中一样?
更新:完整的C++测试代码:
class tobject1 { public: int aaa; };
class tobject2 { public: int bbb; };
class TTest {
tobject1 obj1;
tobject2 obj2;
public:
void doThing() { obj1.aaa = obj2.bbb; };
};
int main()
{
{TTest * test = new TTest; test->doThing(); delete test; }
{TTest test; test.doThing(); }
return 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测试代码:
program Project1;
type
tobject1 = class
aaa: longint;
end;
tobject2 = class
bbb: longint;
end;
TTest = class
obj1: tobject1;
obj2: tobject2;
constructor Create;
destructor Destroy; override;
procedure doThing;
end;
constructor TTest.Create;
begin
inherited;
obj1 := tobject1.Create;
obj2 := tobject2.Create;
end;
destructor TTest.Destroy;
begin
obj1.Free;
obj2.Free;
inherited;
end;
procedure TTest.doThing;
begin
obj1.aaa := obj2.bbb;
end;
var
test: TTest;
begin
test := TTest.Create;
test.doThing;
test.Free;
end.
拆分配代码:
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
此德尔斐对象需要3个的内存分配用于包含的新对象s 2个子对象。如果使用对象而不是记录(因为它们不支持继承,所以它们完全不一样),是否有可能像C++一样减少一个分配(或者如果放在堆栈中,甚至是0)?
在C++版本中也有三种内存分配。在'TTest'构造函数中调用'tobject1'和'tobject2'的默认构造函数。 Delphi没有这个机制,所以你必须手动创建对象。 – Ari0nhh
在子对象上调用默认构造函数和析构函数,但不是新建和删除,C++版本仅为整个对象组合分配一块内存。 – Mardulu
我从来没有尝试过,但你可以玩重写[TObject.NewInstance](http://docwiki.embarcadero.com/Libraries/Seattle/en/System.TObject.NewInstance)。但请注意,这不是Delphi的方式。 –