619 votes

Quelle est la différence entre le passage par référence et le passage par valeur ?

Quelle est la différence entre

  1. un paramètre passé par référence
  2. un paramètre passé par valeur ?

Pouvez-vous me donner des exemples, s'il vous plaît ?

1130voto

Dylan Beattie Points 23222

La meilleure explication que j'ai entendue à ce sujet.

Disons que je veux partager une page web avec vous.

Si je vous donne l'URL, je suis en passant par référence. Vous pouvez utiliser cette URL pour voir le même page web Je peux voir. Si cette page est modifiée, nous voyons tous les deux les changements. Si vous supprimez l'URL, vous ne faites que détruire votre référence à cette page - vous ne supprimez pas la page elle-même.

Si j'imprime la page et que je vous la donne, je suis passer par valeur . Votre page est une copie déconnectée de l'original. Vous ne verrez pas les modifications ultérieures, et les modifications que vous apportez (par exemple, en griffonnant sur votre impression) n'apparaîtront pas sur la page originale. Si vous détruisez l'impression, vous avez en fait détruit votre copie de l'objet - mais la page web originale reste intacte.

171voto

C'est un moyen de passer des arguments aux fonctions. Passer par référence signifie que le paramètre de la fonction appelée sera le même que l'argument passé par l'appelant (pas la valeur, mais l'identité - la variable elle-même). Passer par valeur signifie que le paramètre de la fonction appelée sera une copie de l'argument passé par l'appelant. La valeur sera la même, mais l'identité - la variable - est différente. Ainsi, les modifications apportées à un paramètre par la fonction appelée changent, dans un cas, l'argument transmis et, dans l'autre, la valeur du paramètre dans la fonction appelée (qui n'est qu'une copie). Je suis pressé :

  • Java ne supporte que le passage par valeur. Il copie toujours les arguments, même si, lors de la copie d'une référence à un objet, le paramètre de la fonction appelée pointera vers le même objet et les modifications apportées à cet objet seront vues par l'appelant. Comme cela peut prêter à confusion, ici c'est ce que Jon Skeet a à dire à ce sujet.
  • C# supporte le passage par valeur et le passage par référence (mot-clé ref utilisé chez l'appelant et la fonction appelée). Jon Skeet a également une bonne explication de ceci ici .
  • Le C++ supporte le passage par valeur et le passage par référence (type de paramètre de référence utilisé dans la fonction appelée). Vous trouverez une explication à ce sujet ci-dessous.

Codes

Comme mon langage est le C++, je vais l'utiliser ici.

// passes a pointer (called reference in java) to an integer
void call_by_value(int *p) { // :1
    p = NULL;
}

// passes an integer
void call_by_value(int p) { // :2
    p = 42;
}

// passes an integer by reference
void call_by_reference(int & p) { // :3
    p = 42;
}

// this is the java style of passing references. NULL is called "null" there.
void call_by_value_special(int *p) { // :4
    *p = 10; // changes what p points to ("what p references" in java)
    // only changes the value of the parameter, but *not* of 
    // the argument passed by the caller. thus it's pass-by-value:
    p = NULL;
}

int main() {
    int value = 10;
    int * pointer = &value;

    call_by_value(pointer); // :1
    assert(pointer == &value); // pointer was copied

    call_by_value(value); // :2
    assert(value == 10); // value was copied

    call_by_reference(value); // :3
    assert(value == 42); // value was passed by reference

    call_by_value_special(pointer); // :4
    // pointer was copied but what pointer references was changed.
    assert(value == 10 && pointer == &value);
}

Et un exemple en Java ne fera pas de mal :

class Example {
    int value = 0;

    // similar to :4 case in the c++ example
    static void accept_reference(Example e) { // :1
        e.value++; // will change the referenced object
        e = null; // will only change the parameter
    }

    // similar to the :2 case in the c++ example
    static void accept_primitive(int v) { // :2
        v++; // will only change the parameter
    }        

    public static void main(String... args) {
        int value = 0;
        Example ref = new Example(); // reference

        // note what we pass is the reference, not the object. we can't 
        // pass objects. The reference is copied (pass-by-value).
        accept_reference(ref); // :1
        assert ref != null && ref.value == 1;

        // the primitive int variable is copied
        accept_primitive(value); // :2
        assert value == 0;
    }
}

Wikipedia

http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_value

http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_reference

Ce type a tout compris :

http://javadude.com/articles/passbyvalue.htm

55voto

Eduardo León Points 5364

Voici un exemple :

#include <iostream>

void by_val(int arg) { arg += 2; }
void by_ref(int&arg) { arg += 2; }

int main()
{
    int x = 0;
    by_val(x); std::cout << x << std::endl;  // prints 0
    by_ref(x); std::cout << x << std::endl;  // prints 2

    int y = 0;
    by_ref(y); std::cout << y << std::endl;  // prints 2
    by_val(y); std::cout << y << std::endl;  // prints 2
}

19voto

Craig Points 15049

Lorsque vous passez par ref, vous passez essentiellement un pointeur vers la variable. En passant par value, vous passez une copie de la variable. Dans l'utilisation de base, cela signifie normalement que les changements de la variable passés par ref seront vus par la méthode appelante et que ceux passés par value ne le seront pas.

14voto

ioSamurai Points 8647

Le passage par valeur envoie une COPIE des données stockées dans la variable que vous spécifiez, le passage par référence envoie un lien direct vers la variable elle-même. Ainsi, si vous passez une variable par référence et que vous modifiez ensuite la variable dans le bloc dans lequel vous l'avez passée, la variable originale sera modifiée. Si vous passez simplement par valeur, la variable originale ne pourra pas être modifiée par le bloc dans lequel vous l'avez passée, mais vous obtiendrez une copie de ce qu'elle contenait au moment de l'appel.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X