Dieter: Unterschied call by value vs. call by reference

1. Kann man call by reference

function foo(&$var) {
...
}

foo($var);

prinzipiell der Übersichtlichkeit/ Sicherheit wegen durch

function foo($var) {
...
return $var;
}

$var = foo($var);

ersetzen?

2. Ist call by reference (bemerkbar) schneller? V. a. bei Übergaben, die sehr viel Inhalt haben.

3. In welchen Situationen ist call by reference sinnvoll anzuwenden?

4. Wann ist ein per Aufruf gesetzter call by reference

function foo($var) {
...
(return $var !?)
}

foo(&$var);

sinnvoll?

  1. Moin,
    Ich muss gesetehen, ich kenne mich mit dem PHP-CBR nicht so aus (wusste gar nicht, dass das geht :) ) - aber generell kann ich vielleicht trotzdem was dazu sagen:

    1. Kann man call by reference

    function foo(&$var) {
    ...
    }

    foo($var);

    prinzipiell der Übersichtlichkeit/ Sicherheit wegen durch

    function foo($var) {
    ...
    return $var;
    }

    $var = foo($var);

    ersetzen?

    Ja, können theoretisch schon. Das Problem ist eher, was du tust, wenn du mehrere Variablen in einer Funktion mainpulieren willst, z.b.

    function foo ($a, $b, $c) {
       // Tue irgendwas, veränderte $a, $b, $c

    return (Ja, was nun?)
    }

    Du könntest in diesem Fall ($a, $b und $c) in ein Array packen, dies zurückgeben, dann wieder aufdröseln und den ursprünglichen $a, $b, $c zuweisen - ein bisschen umständlich. Ausserdem: Vielleicht willst du auch noch so etwas wie einen Status zurückgeben, wo soll der dann hin, auch ins Array?

    Mit CBR geht das dann hingegen recht "elegant":

    function foo (&$a, &$b, &$c) {
       //Tue irgendwas

    $completed = true;
       return($completed);
    }

    if (foo ($a, $b, $c)) {
       echo "Everything's fine";
    }
    else {
       echo "Wohoo, something bad happened";
    }

    1. Ist call by reference (bemerkbar) schneller? V. a. bei Übergaben, die sehr viel Inhalt haben.

    Ich würde schätzen nicht messbar schneller. Allerdings:
    Jeder Funktionsaufruf mit CBV legt eine Kopie der übergebenen Variable auf den Stack, die erst wieder gelöscht wird, wenn die Funktion verlassen wird.

    -> Gerade bei Mehrfach-Rekursion erhöht sich durch CBV der Speicherbedarf enorm.

    1. In welchen Situationen ist call by reference sinnvoll anzuwenden?

    Generell immer dann, wenn Du nicht auf Kopien von Variablen sondern auf den Variablen selbst arbeiten willst, sprich, wenn du die Variablen selbst verändern möchtest, und sie nach dem Funktionsaufruf auch verändert bleiben sollen.

    Der Klassiker: Vertauschen zweier Variablen:

    // Funktioniert nicht (logisch, oder)?
    function cbv_swap($a, $b) {
      $c = $b;
      $b = $a;
      $a = $c;

    // Ab hier wird die Kopie von $a und $b wieder gelöscht, nichts
      // hat sich also an den ursprünglichen Variablen geändert
    }

    cbv_swap ($a, $b);

    function cbv_swap(&$a, &$b) {
      $c = $b;
      $b = $a;
      $a = $c;

    // Das geht, a und b sind jetzt vertauscht
    }

    1. Wann ist ein per Aufruf gesetzter call by reference

    function foo($var) {
    ...
    (return $var !?)
    }

    foo(&$var);

    Hier muss ich auf Grund mangelnder PHP Kenntnis passen, aber ich schätze, wenn du eine Funktion bauen willst, die sowohl mit Referenzen als auch mit normalen Variablen umgehen kann, kann so etwas hilfreich sein.

    Viele Grüße,
    Jörg

    1. Hi.

      Du könntest in diesem Fall ($a, $b und $c) in ein Array packen, dies zurückgeben, dann wieder aufdröseln und den ursprünglichen $a, $b, $c zuweisen - ein bisschen umständlich. Ausserdem: Vielleicht willst du auch noch so etwas wie einen Status zurückgeben, wo soll der dann hin, auch ins Array?

      Mit CBR geht das dann hingegen recht "elegant":

      function foo (&$a, &$b, &$c) {
         //Tue irgendwas

      $completed = true;
         return($completed);
      }

      if (foo ($a, $b, $c)) {
         echo "Everything's fine";
      }
      else {
         echo "Wohoo, something bad happened";
      }

      Programmieren habe ich in anderen Sprachen als PHP gelernt. Ich hatte anfangs Probleme mit dem Konzept, daß globale Variablen nur innerhalb der Hauptroutine und nicht in Subroutinen bekannt sind. Das schien mir dem Sinn von global zu widersprechen. Mittlerweile habe ich mich aber daran gewöhnt und finde, es hat Vorteile, schlampigen, unübersichtlichen Programmierstil zu vermeiden. CBR widerspricht diesem Prinzip. Deshalb wollte ich in Erfahrung bringen, wie man es umgehen kann bzw. ob CBR in gewissen Situationen nicht doch vorteilhaft ist. Wenn überhaupt, würde ich einen CBR, der beim Aufruf konstituiert wird, bevorzugen. Das hat auch, wie Du geschrieben hast, den Vorteil, die Funktion sowohl CBV als auch CBR einzusetzen.

      1. Hallo,

        Mittlerweile habe ich mich aber daran gewöhnt und finde, es hat Vorteile, schlampigen, unübersichtlichen Programmierstil zu vermeiden. CBR widerspricht diesem Prinzip. Deshalb wollte ich in Erfahrung bringen, wie man es umgehen kann bzw. ob CBR in gewissen Situationen nicht doch vorteilhaft ist.

        Du weisst, dass sich in PHP inzwischen (ich glaube seit Version 4) auch sehr schön objekt-orientiert programmieren lässt, oder?
        Das ist nach meinem Dafürhalten immer noch die sauberste Form für größere Projekte (keine bzw. wenige globale Variablen, nur noch Klassen, Instanzen und Methoden), und damit erübrigen sich viele klassische CBR-Aufgaben und damit verbundene Probleme.

        Das war nämlich auch der Grund, warum mir das bei PHP bisher entgangen ist, mein erstes (etwas größeres) PHP-Projekt war in PHP5 und von daher bereits objekt-orientiert.

        In klassichem C (also != C++) hingegen z.b. gibt es ja keine Objektorienierung, hier muss man sich schier mit CBR-Methodiken behelfen.

    2. Hi,

      Du könntest in diesem Fall ($a, $b und $c) in ein Array packen, dies zurückgeben, dann wieder aufdröseln und den ursprünglichen $a, $b, $c zuweisen - ein bisschen umständlich.

      Wenn man das häufiger macht, dann schreibt man sich sicher eine komfortable Funktion dafür (wenn die eingebauten wie list nicht komfortable genug sind). Würde ich jedenfalls machen - bzw. habe ich als PHP-Programmierer natürlich gemacht. ;-)

      Ich nutze zwar CBR auch ab und zu mal, aber mich nervt, das CBRs nicht optional sein können. Und ich schreibe meine Funktionen am liebsten so, daß sie ohne bzw. wenigstens mit möglichst wenigen Parametern aufgerufen werden können.

      Gruß, Cybaer

      --
      Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
  2. echo $begrüßung;

    1. Kann man call by reference [...] prinzipiell der Übersichtlichkeit/ Sicherheit wegen durch [...] ersetzen?

    Prinzipiell kann man das nicht beantworten. Prinzipell sollte man aber Referenzen nur dann verwenden, wenn es technisch notwendig ist. (Vergleiche: http://de.php.net/manual/en/language.references.return.php)

    1. Ist call by reference (bemerkbar) schneller? V. a. bei Übergaben, die sehr viel Inhalt haben.

    Sicher nicht, denn PHP fertigt nicht wirklich eine Kopie an. Erst wenn die Werte auseinander laufen wird die Kopie erstellt. Das Erzeugen der Referenz verbraucht auch Zeit. Außerdem ist es sicher ein Unterschied, ob du eine komplexe Struktur (Array, Objekt) hast oder nur einen großen String. Letzterer sollte sich in einem Zug kopieren lassen, die anderen eher nicht.

    Literaturtipp: References Explained (by Derick Rethans) (Dieser Link versteckt sich im PHP-Handbuch unter debug_zval_dump().)

    1. In welchen Situationen ist call by reference sinnvoll anzuwenden?

    Wenn du eine Referenz auf die originalen Daten benötigst. Das gilt aber nicht für Objekte unter PHP5, denn die werden immer als Referenz übergeben. Hier musst du clone verwenden, um eine Kopie zu erzeugen.

    1. Wann ist ein per Aufruf gesetzter call by reference sinnvoll?

    Nur dann, wenn man allow_call_time_pass_reference eingeschaltet hat und nachdem man die Beschreibung dazu gelesen hat. ;-)
    Außerdem ist es notwendig, wenn man unter PHP4 eine Methode als callback angeben möchte.

    echo "$verabschiedung $name";

    1. Literaturtipp: References Explained (by Derick Rethans)

      Sehr schöner Artikel; vielen Dank für den Hinweis.

      Grüsse