【发布时间】:2017-06-01 05:30:34
【问题描述】:
我希望包含在其他对象中的对象不必分配它们的内存。例如在 Delphi 中我可以这样写:
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 个。有没有办法在 Delphi 中为一个完整的对象及其子对象只分配一个内存,就像在 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
这个 Delphi 对象需要为一个包含 2 个子对象的新对象分配 3 次内存。是否可以使用对象而不是记录(它们根本不一样,因为它们不支持继承)来减少像 C++ 中那样的一个分配(如果放在堆栈上,甚至是 0)?
【问题讨论】:
-
c++ 版本也有三种内存分配。
tobject1和tobject2的默认构造函数在TTest构造函数中调用。 Delphi 没有这个机制,所以你必须手动创建对象。 -
子对象调用默认的构造函数和析构函数,但不调用new和delete,c++版本只为整个对象组合分配一块内存。
-
我从未尝试过,但您可以使用覆盖 TObject.NewInstance。但请注意,这不是 Delphi 的方式。
-
另一种可能性是使用
records,它是像C++structs 这样的值类型,而delphiclasses 是像C#/Java 那样的引用类型。 -
你想要的对于类实例是不可行的。
标签: delphi