Question

J'étudie Java depuis quelques mois et je commence maintenant à apprendre le C.

Je suis un peu confus, j'avais l'impression que transmettre un objet par référence et un pointeur sur cet objet était la même chose: je pensais que la différence était qu'en Java tous les objets passaient automatiquement avec des pointeurs, où, comme en C, il faut réellement saupoudrer de petits astérisques et esperluettes ici et là. Récemment, lors d'une conversation, on m'a assuré qu'il y avait une différence!

Quelle est la différence entre le passage par référence et le passage d'un pointeur?

Était-ce utile?

La solution

Ni Java ni C ne disposent pas de références par référence. Ils sont tous les deux strictement pass-par-valeur.

La sémantique passe-à-référence signifie que lorsque vous modifiez la valeur du paramètre dans la méthode, l'appelant verra ce changement dans l'argument.

Maintenant, vous pensez peut-être: "Mais c'est le cas en Java! Si je modifie un objet au cours de la méthode, l'appelant voit cette modification. & Quot; L'objet n'est pas le paramètre. Le paramètre est juste la variable - et si vous modifiez la valeur de cette variable, l'appelant ne le verra pas. Par exemple:

public void foo(Object x)
{
    x = null;
}

public void caller()
{
    Object y = new Object();
    foo(y);
    // y is still not null!
}

Si le paramètre était vraiment passé par référence, y serait nul par la suite. Au lieu de cela, la valeur de y est simplement une référence et cette référence est passée par valeur. C'est déroutant parce que le mot "référence" est dans les deux termes, mais ce sont des choses différentes.

Vous pouvez consulter mon article sur le passage de paramètres C # à voir Que serait-il possible si Java avait une sémantique passe par référence, comme le fait C # quand (et seulement quand) vous utilisez le mot clé ref .

Vous pouvez également consulter les commentaires sur mon Réponse de débordement de pile relative au sujet.

Autres conseils

  

Je pensais que la différence était qu'en Java, tout passage d'objets se faisait automatiquement avec des pointeurs, alors qu'en C, il fallait réellement saupoudrer de petits astérisques et esperluettes ici et là.

Conception, c'est tout à fait vrai. Si nous sommes pédants (et c'est une bonne chose), nous pouvons même dire que les objets ne sont pas du tout passés en Java. Ce qui est passé n’est que le "pointeur", qui en Java est appelé la référence. Toute indirection est faite automatiquement. Alors, quand vous faites & objref- > foo " au lieu de " objref.foo " en C et ne peut pas utiliser le point parce que vous travaillez avec un pointeur, en Java, vous pouvez toujours utiliser le point car il ne sait pas quoi que ce soit d'autre pour accéder aux membres. En C, vous pouvez passer le pointeur (et ici, il est appelé réellement pointeur) et vous pouvez passer l'objet lui-même, auquel cas une copie est transmise. En C, vous accédez à l’objet auquel un pointeur se réfère par indirection à l’aide de l’étoile ou du signe - - > " En Java, le seul moyen d'accéder aux objets consiste à utiliser le point (objref.member).

Si nous sommes à nouveau pédants (plus importants encore), ni en Java ni en C, il n'y a "passe par référence". Ce que nous transmettons en Java est la référence / le pointeur sur l'objet et en C, nous transmettons une copie de l'objet (cas évident) ou nous ne transmettons qu'une copie du pointeur sur l'objet. Donc dans les deux cas - Java et C - ce que nous passons sont les adresses des objets. Ne parlons pas des types java primitifs, qui sont copiés à la fois en Java et en C - même si vous pouvez également transmettre leur adresse en C, il n'y a pas de différence entre un type d'agrégat (c'est-à-dire un struct) et un "type primitif". en C dans cet égard.

Les différences sont subtiles. Au niveau de l'assemblage, dans les deux cas, l'adresse de l'objet est transmise à la fonction. Toutefois, dans le cas du pointeur, le paramètre est un pointeur indépendant pouvant être utilisé pour modifier l'objet cible (* pch = 'x') ou pour accéder à un autre objet (pch = "newstr"). Dans le cas de référence, le paramètre est automatiquement induit sur l'objet cible.

Je pense qu'un pointeur est une variable qui contient une référence. Avec & amp; vous pouvez obtenir un sens de la mémoire (référence) et avec * vous pouvez accéder au contenu d'un sens de la mémoire. Je suggère le livre Le langage de programmation C .

Cordialement

Vrai référence par référence vous permet d'attribuer une nouvelle valeur à la référence, et cette nouvelle valeur sera visible dans le contexte de l'appel, comme dans la méthode appelée.

En Java, cela n’est pas possible car les références d'objet sont passées par valeur .

Quelques petites choses

  • C n'a pas de références (malgré C ++)
  • Java n'a pas de pointeur
  • La différence entre les pointeurs et les références est que les pointeurs sont pratiquement des adresses de mémoire avec lesquelles vous pouvez calculer. Les références ne peuvent pas être calculées avec
  • Java et C passage par valeur (lors du passage d'un objet en Java, la référence est copiée dans la fonction)

Si vous étudiez le C (plutôt que le C ++), il n'y a pas de références.

Le terme "transmettre par référence" in C signifie simplement que vous passez un pointeur en tant qu’adresse dans laquelle la valeur sera stockée, de sorte que la fonction puisse modifier sa valeur. Sinon, vous passez par valeur, ce qui signifie qu'une copie de la variable est générée sur la pile et que les modifications n'ont aucun impact.

À bien des égards, cela ressemble à ce que vous voyez en Java, sauf que vous n'avez pas à transformer explicitement les choses en pointeur ou à les déréférencer. En d'autres termes, lorsque vous passez un pointeur, l'adresse est copiée sur la pile. Ainsi, si votre fonction modifie le pointeur (plutôt que les données vers lesquelles elle pointe), les modifications disparaissent lorsque vous avez terminé avec la fonction. De même, lorsque vous transmettez une référence d'objet en Java, vous pouvez modifier le contenu de l'objet (par exemple, en appelant des fonctions), mais le fait de changer la variable pour pointer vers un autre objet n'aura aucun effet une fois que vous aurez quitté.

Si vous utilisiez C ++ (qui ressemble à C), vous pouvez alors passer par référence. Dans ce cas, vous n'avez pas besoin de gérer les pointeurs. Les modifications apportées à la variable dans la fonction modifient directement la valeur externe ( sauf que vous ne pouvez pas faire le point sur quelque chose d'autre).

Il y a un article récent d'Eric Lippert à ce sujet. Il est programmeur sur le compilateur C #, mais quoi qu'il dise, il y a suffisamment de généralité pour être étendu à d'autres langages du GC, tels que Java:

http: // blogs .msdn.com / ericlippert / archive / 2009/02/17 / références-ne-sont-pas-adresses.aspx

Citation de l'article:

  

Les pointeurs sont strictement "plus puissants". que des références; tout ce que vous pouvez faire avec des références que vous pouvez faire avec des pointeurs. [...]

     

Les pointeurs sont généralement implémentés en tant qu'adresses. Une adresse est un nombre qui correspond à un décalage dans le "tableau d'octets". c'est tout l'espace d'adressage virtuel du processus. [...]

     

Pour toutes ces raisons, nous ne décrivons pas les références comme des adresses dans la spécification. La spécification indique simplement qu'une variable de type référence "stocke une référence". à un objet, et laisse complètement vague quant à la façon dont cela pourrait être mis en œuvre. De même, une variable de pointeur stocke " l'adresse " d'un objet, qui encore est laissé assez vague. Nous ne disons nulle part que les références sont les mêmes que les adresses.

     

Ainsi, en C #, une référence est un élément vague qui vous permet de référencer un objet. Vous ne pouvez rien faire avec une référence sauf la déréférencer et la comparer à une autre référence pour l'égalité. Et en C #, un pointeur est identifié en tant qu’adresse.

     

Contrairement à une référence, vous pouvez faire beaucoup plus avec un pointeur contenant une adresse. Les adresses peuvent être manipulées mathématiquement. vous pouvez les soustraire les unes des autres, vous pouvez leur ajouter des nombres entiers, etc. Leurs opérations juridiques indiquent qu’il s’agit de "chiffres fantaisistes". cet index dans le "tableau" c'est l'espace d'adressage virtuel du processus.

Les lecteurs qui maîtrisent le C / C ++ ont probablement remarqué la présence de références d'objet être semblable aux pointeurs. Ce soupçon est, pour l’essentiel, correct. Une référence d'objet est semblable à un pointeur de mémoire. La principale différence et la clé de la sécurité de Java sont les suivantes: vous ne pouvez pas manipuler les références comme vous pouvez les pointeurs réels. Ainsi, vous ne pouvez pas causer un référence d'objet pour pointer vers un emplacement mémoire arbitraire ou pour le manipuler comme un entier.

  • java non pris en charge & amp; opérateur alors comment pouvez-vous obtenir l'adresse de l'objet en java.
  • En Java, la référence est faite par objet, par exemple

MyClass object1 = new MyClass ();

MyClass object2 = object1;

i.e. vous pourriez penser que objet1 et objet2 font référence à des objets séparés et distincts. Cependant, ce serait faux. Au lieu de cela, après l'exécution de ce fragment, object1 et object2 feront tous deux référence au même objet. si vous changez l'un ou l'autre effet.

* vous ne pouvez pas changer l'adresse de l'objet après l'initialisation i.e MyClass obj = new MyClass (); comme référence en c ++, avec objet, vous ne pouvez modifier que la valeur d'instance d'objet

Remarque: Java fournit une fonctionnalité spéciale.         object1 a été défini sur null, mais object2 pointe toujours sur l'objet d'origine.

Je ne suis pas sûr de java mais en C # ou VB.net vous pouvez passer par valeur ou par référence

exemple passant par réfraction

    static void Main(string[] args)
    {
        int x = 1;
        Foo(ref x);
        Console.WriteLine(x.ToString());//this will print 2
    }

    private static void Foo(ref int x)
    {
        x++;
    }

remarquez que x est égal à 1, mais lorsque vous appelez la méthode Foo et transmettez x par réfraction lorsque x est augmenté de un dans Foo, la valeur d'origine est également augmentée

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top