Avatar billede alvion Nybegynder
07. januar 2004 - 10:43 Der er 6 kommentarer og
1 løsning

Arrays med referencer til værdier/objekter

Jeg sidder og arbejder med arrays, hvor elementerne er referencer til objekter. Men metoden til at indsætte dem på er lidt mærkværdig. Derfor har jeg lavet følgende lille test, som jeg gerne vil have et par kommentarer på.

Se på følgende kode:
------------------------------
$arr = array();
$k = 5;

$arr[] = &$k;
echo $arr[0] // giver 5

$k = 6;
echo $arr[0] // giver 6
------------------------------

Hvad jeg i virkeligheden GERNE vil have er, at $k kunne "genbruges" uden at det påvirker $arr[0]. Det kunne jeg selvfølgelig gøre ved bare at sige $arr[] = $k, for så vil $arr[0] indeholde en kopi.

MEN eksemplet er også kun hypotetisk. Forestil istedet, at $k var en instans af en klasse:

$k = new MyClass(...)

Denne instans indeholder selv andre refererede objekter, og har derfor ikke godt af at blive kopieret.

Så mit ønske er at kunne "deponere" instansen i array'et, og bruge $k til at oprette en ny instans, som så også skal gemmes i array'et osv.

Jeg kan gøre det således:
--------------------------
function array_add(&$a, &$item) {
    $a[] = $item;
}

$arr = array();
$k = 5;

array_add($arr, $k);
echo $arr[0] // giver 5

$k = 6;
echo $arr[0] // giver stadig 5
--------------------------

Dvs. jeg bruger en hjememstrikket funktion til formålet, som tager elementet som en reference.

Findes der en mere elegang PHP konstruktion til formålet?
Avatar billede alvion Nybegynder
07. januar 2004 - 11:01 #1
Jeg ved at spørgsmålet bliver underordnet, når PHP 5 engang er færdig. For i PHP5/Zend2 oprettes alle objekter automatisk som referencer. Men jeg har problemet lige nu. :-)
Avatar billede jakoba Nybegynder
07. januar 2004 - 21:36 #2
Du kommer til at forklare noget bedre. efter beskrivelsen ville jeg påstaå at det du ønsker er det du får pr default:

$k = array( 1, 2, 3 );
$lager[] = $k;
$k = array( 4, 5, 6 );
$lager[] = $k;
echo "lager[0][1] er " .$lager[0][1]
    ", lager[1][1] er " .$lager[1][1];
// skriver "lager[0][1] er 2, lager[1][1] er 5";

nårsomhelst to assigner et Objekt til en variabel er det i virkeligheden en reference til det objekt der bliver assignet.

mvh JakobA
Avatar billede jakoba Nybegynder
07. januar 2004 - 21:38 #3
Ups. der mangler et '.' til at forbinde de to linier i echo ...
echo "lager[0][1] er " .$lager[0][1]
    . ", lager[1][1] er " .$lager[1][1];
Avatar billede alvion Nybegynder
09. januar 2004 - 10:04 #4
"nårsomhelst to assigner et Objekt til en variabel er det i virkeligheden en reference til det objekt der bliver assignet."

um... nej det er ikke korrekt. Tag dette eksempel:

$a = new MinKlasse();
$b = $a;

$a og $b indeholder nu to FORSKELLIGE instanser af MinKlasse. Og det er netop fordi at denne assignment laver en kopi af $a's instans. Din tese er korrekt fra PHP version 5.0 (pga. den nye Zend 2.0).

Det er MULIGT, at $a kun indeholder en reference til objektet (instansen), men hvis man assigner den til $b, så kopieres objektet til et nyt.
Avatar billede alvion Nybegynder
09. januar 2004 - 10:08 #5
Tag følgende eksempel:
-------------------------
echo "<pre>";
class MinKlasse {
}

$a = new MinKlasse();
$a->k = 5;
print_r($a);

$b = $a;
print_r($b);

$a->k = 6;
print_r($b);

echo "</pre>";
-------------------------
Giver dette output

minklasse Object
(
    [k] => 5
)
minklasse Object
(
    [k] => 5
)
minklasse Object
(
    [k] => 5
)

Hvis $b havde fået $a's reference, så skulle den sidste print vise

minklasse Object
(
    [k] => 6
)
Avatar billede alvion Nybegynder
09. januar 2004 - 10:16 #6
Ok, sidste formulering - og en løsning på mit oprindelige problem, som PLUDSELIG dumpede ned i hovedet på mig :)

Mit sidste ovenstående eksempel løses ved at sige:

$b = &$a;

Så peger $b og $a på samme objekt. Mit oprindelige problem var så, at jeg ønskede at "deponere" objektet i $b, og så bagefter bruge variablen $a til et helt andet formål. Sagt på en anden måde i et eksempel:

$lager = array();

for ($i=0; $i<10; $i++) {
  $temp = new MinKlasse($i);
  $temp->gørnogetmere();
  $lager[] = &$temp
}

Ovenstående virker ikke, fordi der sker følgende:

1) $temp assignes objektet MinKlasse(0)
2) $lager[0] assignes samme objekt MinKlasse(0)
3) næste loop
4) $temp assignes objektet MinKlasse(1) - SAMTIDIG assignes $lager[0] MinKlasse(1)
5) $lager[1] assignes objektet MinKlasse(1)

Allerede nu er den gået galt. Lager indeholder:

$lager[0] => MinKlasse(1)
$lager[1] => MinKlasse(1)

hvor den skulle indeholde

$lager[0] => MinKlasse(0)
$lager[1] => MinKlasse(1)

Men nu har jeg fundet (en frygtelig simpel) løsning:

for ($i=0; $i<10; $i++) {
  $temp = new MinKlasse($i);
  $temp->gørnogetmere();
  $lager[] = &$temp
  unset($temp);
}

At det skulle være så nemt............. ;-)
Avatar billede alvion Nybegynder
19. februar 2004 - 01:23 #7
så lukker vi
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester