[delphi] copy-assignment

Pagina: 1
Acties:
  • 100 views sinds 30-01-2008
  • Reageer

  • Jelmer
  • Registratie: Maart 2000
  • Laatst online: 13:28
Na de afgelopen weken veel met c++ te hebben moeten werken ben ik nu in delphi tegen een groot gemis aangelopen. Althans, ik zie zo snel niet of delphi deze functie standaard al aan boord heeft.
Met c++ heb ik geleerd dat als je een object hebt en dat met operator= toekent aan een andere variable van het zelfde type de boel automatisch, bit voor bit wordt gekopieerd.

Delphi heeft de := operator. Dit is een gewone assignment. Dus als ik nu een object a aan b wil toekennen, wordt doodleuk het adres van a in b gezet!

Dit is natuurlijk wel op te lossen door zelf een clone functie te schrijven, maar ik vroeg me dus af of Delphi niet zelf een copy-assignment operator of functie aan boord heeft..

  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 08-09 08:43

Bergen

Spellingscontroleur

Zoek eens op Assign... volgens mij vind je daar je antwoord:

Override Assign to copy data from one object to another object of the same type. A small number of Delphi classes also support assignment to objects of different types; in all other cases, if two objects are descended from TPersistent but are not of the same type, the call to Assign raises an EConvertError exception.
The standard form of a call to Assign is

Destination.Assign(Source);

which tells the Destination object to copy the contents of the Source object to itself. In general, the statement Destination := Source is not the same as the statement Destination.Assign(Source). The statement Destination := Source makes Destination reference the same object as Source, whereas "Destination.Assign(Source)" copies the contents of the object referenced by Source into the different object referenced by Destination.

Note

The types of some properties are also objects. If these properties have write methods that use Assign to set the value of the property, then in these cases the statement "Destination := Source" is the same as "Destination.Assign(Source)".
Conversion can happen in either the Assign method or the AssignTo method. The difference is in who does the work to implement the assignment.
Note also that Source can be nil.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op donderdag 11 oktober 2001 00:51 schreef Jelmer Barhorst het volgende:
[...knip...>
No offense maar je staat een bout onzin te verkopen :Y)

C++ kopieert pointers net zo 'hard' als Delphi: gewoon het geheugenadres kopieren, dat is juist het idee erachter. Als je in C++ een simpele struct of een class met een expliciete copy-constructor of operator= overload op deze manier toewijst, kopieert ie het hele ding inderdaad. Lijkt me errug sterk dat Delphi dit niet kan met [b]simpele[b] objecten (desnoods iets in de richting van dereferencen eerst).

Wat jij echter waarschijnlijk probeert de doen is een TButton of zo te kopieren, en daar alle TComponents van VCL van TPersistent afgeleidt zijn heb je zoals Gerben al meldt inderdaad de beschikking over Assign. Zie het volgende stukje C++Builder code:
code:
1
2
3
4
5
6
7
8
9
// Consider Button to be an existing button on the form
TButton*    CopyButton;

// Perform copy of pointer without duplicating:
CopyButton    = Button;

// Create clone:
CopyButton    = new TButton(Button->Owner);
CopyButton->Assign(Button);

Hopelijk kun je hier iets mee :)

Professionele website nodig?


  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 08-09 08:43

Bergen

Spellingscontroleur

Hier wil ik nog wel even over doorpraten want ik zit er ook effe mee te prutsen.

Voor de duidelijkheid: Je kunt dus het geheugenadres van een variabele op 2 manieren opvragen:
code:
1
2
3
4
5
6
7
8
var
   hetAdres, eenVariabele: integer;
begin
   // manier 1
   hetAdres := integer ( Addr(eenVariabele) );
   // manier 2
   hetAdres := integer ( @eenVariabele );
end;

Maar als ik gewoon 2 integers aanmaak en dan b := a; doe dan heet b echt niet het adres van a!! Zo doe ik het:
code:
1
2
3
4
5
6
7
var
   a, b: integer;
begin
   b := a;
   edit1.text := IntToStr ( integer(@a) );
   edit2.text := IntToStr ( integer(@b) );
end;

Dan krijg ik dus dit:

Afbeeldingslocatie: http://www.xs4all.nl/~gurbe/got/poging0.jpg

Nou was ik nog even verder aan het prutsen met pointers en ik probeer een stukje geheugen te allocaten om een getalletje in op te slaan, een 2 erin te gooien en die vervolgens op het scherm te krijgen. Ok, de 2 komt op het scherm maar wel met een Access Violation Exception. Waarom? Code:
code:
1
2
3
4
5
6
7
8
var
   a, b: Pointer;
begin
    GetMem (a, 4);
    integer (a) := 2;
    edit1.text := IntToStr ( integer (a) );
    FreeMem (a);
end;

Ook heb ik al dingen al a^ := 2; en ^a := 2; geprobeerd maar ik snap er ff geen zak meer van wanneer en waar je nou dat dakje ^ gebruikt.

Wel weet ik dat als ik een type aanmaak dat ik er als volgt een pointer naar toe gooi bij de typedeclaraties:
code:
1
2
3
4
5
type
   PDing = ^TDing;
   TDing = record
    ietsInHetDing: byte;
   end;

Toch? Een hele hoop vragen maar wel interesting dacht ik zo :]

  • Jelmer
  • Registratie: Maart 2000
  • Laatst online: 13:28
GerbenW, dat is inderdaad wat ik zocht ja.. Snap ook waarom ik er waarschijnlijk overheen heb gekeken: het valt niet onder TObject maar onder TPersistent en laat ik nou net TObject voor inheritance gebruikt te hebben... Maar in iedergeval bedankt, hier kan ik een eind mee komen.
Vanmiddag ga ik ook zeker nog even prutsen met die pointers in delphi, zeker interressant.

Curry684, ik heb ook nog even met c++ gespeeld en idd als ik een instantie van een klasse op de volgende manier aan een nieuwe variabele toeken, wordt het adres hard gekopieerd:
code:
1
2
    Test * p1 = new Test (6);
    Test * p2 = p1;

Maar als ik het als volgt doe, gaat het wel!
code:
1
2
3
4
    Test t1 (5);
    Test t2 (1);
    t2=t1;
    t2.a=3;

Hier staat de c++ code die ik met GNU c++ heb gecompiled.

Dus pure onzin sta ik niet te verkopen volgens mij!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 16:25

Creepy

Tactical Espionage Splatterer

Op donderdag 11 oktober 2001 04:27 schreef GerbenW het volgende:
Hier wil ik nog wel even over doorpraten want ik zit er ook effe mee te prutsen.

Voor de duidelijkheid: Je kunt dus het geheugenadres van een variabele op 2 manieren opvragen:
code:
1
2
3
4
5
6
7
8
var
   hetAdres, eenVariabele: integer;
begin
   // manier 1
   hetAdres := integer ( Addr(eenVariabele) );
   // manier 2
   hetAdres := integer ( @eenVariabele );
end;

Maar als ik gewoon 2 integers aanmaak en dan b := a; doe dan heet b echt niet het adres van a!! Zo doe ik het:
code:
1
2
3
4
5
6
7
var
   a, b: integer;
begin
   b := a;
   edit1.text := IntToStr ( integer(@a) );
   edit2.text := IntToStr ( integer(@b) );
end;

Dan krijg ik dus dit:

[afbeelding]

Nou was ik nog even verder aan het prutsen met pointers en ik probeer een stukje geheugen te allocaten om een getalletje in op te slaan, een 2 erin te gooien en die vervolgens op het scherm te krijgen. Ok, de 2 komt op het scherm maar wel met een Access Violation Exception. Waarom? Code:
code:
1
2
3
4
5
6
7
8
var
   a, b: Pointer;
begin
    GetMem (a, 4);
    integer (a) := 2;
    edit1.text := IntToStr ( integer (a) );
    FreeMem (a);
end;

Ook heb ik al dingen al a^ := 2; en ^a := 2; geprobeerd maar ik snap er ff geen zak meer van wanneer en waar je nou dat dakje ^ gebruikt.

Wel weet ik dat als ik een type aanmaak dat ik er als volgt een pointer naar toe gooi bij de typedeclaraties:
code:
1
2
3
4
5
type
   PDing = ^TDing;
   TDing = record
    ietsInHetDing: byte;
   end;

Toch? Een hele hoop vragen maar wel interesting dacht ik zo :]
Het dakje ( ^ ) is puur voor pointers! Een pointer kan je zien als een variabele waar een geheugen adres in staat! Met het dakje heb je de inhoud van dat adres!
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var a,b: integer;
begin
     a:=1;
     b:=2;
     a:=b; // de INHOUD van a is nu de inhoud van B
end;


var a,b: ^integer;  // pointer (^) naar een int!
begin
     new(a);  // dit zijn typed pointers, dus kunnen we 
     new(b);  // new() gebruiken voor geheugen toekenning
     a^:=1;
     b^:=2;
     a^:=b^;  // dit is hetzelfde als hierboven!
          // de adresses van a en b zijn verschillend

    a:=b;     // Oops... adres van a is nu ook dat van b
          // Als a^ nu veranderd word, is b^ ook veranderd.
          // En meteeen heb je eem mem-leak, want het oude adres van a is verloren gegaan

end;

Een pointer is gewoon een variabele, maar zonder het ^ zit je met de geheugen adressen te spelen. Dit is btw hetzelfde als in C. zonder * heb je het adres, met * heb je de inhoud van het adres waar de pointer naar wijst.

En wat dacht je hiervan:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var a, b: Pointer;
begin
    GetMem (a, 4);
    integer (a)^ := 2; // aarrrhh.. dat dakje niet vergeten!
                 // JE bent niet met het adres, maar met de inhoud van het adres aan het spelen
    // met integer (a) := 2 cast je het adres om naar een int, 
    //en ken je 2 aan toe... a wijst nu naar geheugen plek 2 (wat dat ook mogen wezen)

    edit1.text := IntToStr ( integer (a)^ ); // en weer dat dakje :) 
               //We zijn met de inhoud van het adres waar a naar wijst aan het spelen! Niet met het adres zelf!

    //Dit edit1.text := IntToStr ( integer (a) ); geeft natuurlijk wel 2 terug 
    //(als je hiervoor al geen access violation hebt gehad). 
    //Aangezien je aan het adres 2 toekende, en het adres weer opvraagt, en dus NIET de inhoud van het adres

    FreeMem (a);
end;

Oftewel in het kort: Een pointer is een VERWIJZING!
Als je met de pointer aan het spelen bent, speel je met het adres! Als je wilt spelen met waar de pointer naar wijst,Wijs dan ook! (het ^.. dakje, pijltje naar boven.. blaat.. pijltje dus :) en een pijl wijst.)

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op donderdag 11 oktober 2001 09:00 schreef Jelmer Barhorst het volgende:
Maar als ik het als volgt doe, gaat het wel!
code:
1
2
3
4
    Test t1 (5);
    Test t2 (1);
    t2=t1;
    t2.a=3;
Dat zei ik, een simpele class of een class met copy-constructor.

Professionele website nodig?

Pagina: 1