Quelle est la différence entre passer par référence et passer par valeur?
Quelle est la différence entre
- paramètre passé par référence
- un paramètre passé par valeur?
Pourriez-vous me donner quelques exemples, s'il vous plaît?
17 réponses
la chose probablement la plus importante à savoir au sujet de la distinction appel par valeur par rapport à appel par référence est que l'idée qui a été décrite à l'origine comme" appel par référence "existe à peine plus . Sauf si vous programmez dans Fortran ou Visual Basic, ce n'est pas le comportement par défaut, et dans la plupart des langues modernes, vrai appel-par-référence n'est même pas possible.
cependant, un mécanisme similaire est possible, et ce mécanisme similaire est souvent confondu avec appel par référence, au point que certaines personnes utilisent à tort le terme "Appel par référence" pour se référer à cet autre comportement.
la clé pour comprendre est que le mot" référence "dans l'expression" appel par référence "n'est pas la même chose que le mot" référence " signifie dans d'autres contextes. En outre, Java a décidé d'utiliser le mot "référence" pour signifier la chose que les gens appelaient auparavant "pointeur", et C# et plusieurs autres langues il suit L'usage de Java, tandis que C++ utilise une signification pour "référence" qui est différente de la signification de Java et aussi distincte de la signification de "appel par référence".
maintenant, la définition authentique est:
-
Lorsqu'un paramètre est passé par référence , l'appelant et l'appelé utiliser la même variable pour le paramètre. Si le destinataire de l'appel modifie paramètre variable, l'effet est visible à l'appelant de la variable.
-
Lorsqu'un paramètre est passés par valeur , l'appelant et l'appelant ont deux variables indépendantes avec la même valeur. Si l'appelant modifie la variable paramètre, l'effet n'est pas visible pour l'appelant.
notez que "variable" signifie ici l'appelant (local ou global) variable elle-même -- c'est-à-dire, si je passe une variable locale par référence et lui attribue, je changerai la variable de l'appelant elle-même. La plupart des nouveaux langages n'ont pas ce mécanisme. Lorsque les nouvelles langues ont un mécanisme similaire, il faut une syntaxe explicite pour marquer un paramètre de fonction comme un paramètre d'entrée/sortie ou de sortie seulement, et les paramètres d'entrée seulement (c'est-à-dire, appel-par-valeur) sont la valeur par défaut. ("Plus récent" signifie ici à peu près n'importe quel langage inventé depuis 1970; pour par exemple, la syntaxe de référence de C++rend le comportement appel par référence possible, mais il doit être explicite dans la déclaration des paramètres, tandis que le comportement par défaut de C++est appel par valeur.)
le "mécanisme similaire" mentionné ci-dessus est l'idée de "types de référence", c'est-à-dire des valeurs où l'objet "valeur" réel est stocké séparément de la variable qui est utilisée pour y accéder. (Généralement, l'objet réel est stocké dans le tas d'application, mais pas nécessairement. Dans plusieurs langues modernes, toutes les variables sont des types de référence -- cette approche a été lancée par le language CLU en 1975 et a depuis été adoptée par de nombreuses autres langues, dont Python et Ruby. Et beaucoup d'autres langages utilisent une approche hybride, où certains types sont des " types de valeurs "et d'autres sont des" types de référence " -- parmi eux sont C#, Java, et JavaScript.
le concept est similaire mais se produit avec un niveau supplémentaire d'indirecte. Avec les types de référence, la stratégie d'appel normale est que les arguments soient passés en utilisant les objets valeur réelle, plutôt que les variables qui s'y rapportent. Cela est très similaire à la façon dont pass-by-référence fonctionne, mais ce n'est pas la même chose, parce que seulement mutations aux objets référencés , pas réaffectations , deviennent visibles à l'appelant.
cela conduit à une confusion supplémentaire parce que tous les objets ne peuvent pas être mutés. Dans certaines langues, tous les objets sont mutables; dans d'autres, un objet peut être immuable (par spécification de langue ou par intention de programmeur, selon la langue); dans d'autres langues encore, tous les objets sont immuables. En conséquence, certaines personnes ont été amenées à croire que les objets mutables et immuables sont passés différemment, ce qui n'est pas vrai dans n'importe quel langage de programmation. (Haskell couvertures en exigeant que tous les objet immuable; en conséquence, si Haskell utilise en appel par valeur ou call-by-reference est un détail d'implémentation du compilateur.)
tout cela conduit à des explications déformées comme" appel par valeur où la valeur est une référence", ce qui est en fait la stratégie d'évaluation la plus courante aujourd'hui. En 1975, Barbara Liskov a inventé le terme call-by-object-sharing "(ou parfois juste" call-by-sharing") pour décrire cette stratégie, qui est plus correcte que" call-by-reference", plus précise que" call-by-value", et plus court que "l'appel-par-valeur-de-une-reference-type)". Malheureusement, la terminologie de Liskov n'a pas pris dans les années intermédiaires.
NOTE : pendant longtemps, cette réponse a été mal lue:
dites que je veux partager une page Web avec vous. Si je vous dis L'URL, Je suis le passage par référence. Vous pouvez utiliser cette URL pour voir la même page Web I pouvez le voir. Si cette page est changée, nous afin de voir les changements. Si vous supprimer L'URL, tout ce que vous faites est de détruire votre référence à ce page-vous ne supprimez pas la page elle-même.
si j'imprime la page et que je vous donne l'impression, je passe devant valeur. Votre page est une copie déconnectée de l'original. Vous ne verrez pas tous les changements ultérieurs, et tous les changements que vous apportez (par exemple gribouiller sur votre impression) ne sera pas affiché sur la page d'origine. Si vous détruire l'impression, vous avez effectivement détruit votre copie de la objet-mais la page Web originale reste intacte.
il est une analogie simple qui est facile à comprendre, qui a obtenu ce poste des centaines d'upvotes. Cependant, l'analogie est erronée: appel par référence et appel par valeur ne sont pas comme les URLs. (Un type de référence dans un langage comme C#, c'est comme une URL; voir Jon Skeet de la grande écriture-up sur les types de référence .NET pour plus de détails. Mais types de référence ne sont pas la même chose que passage par référence .)
puisque cette analogie n'est pas correcte, elle a été supprimée de cette réponse. Elle a depuis été rétablie en tant qu'exemple de la conception erronée la plus répandue du fonctionnement d'un appel par référence.
C'est une façon de passer des arguments à des fonctions. Passer par référence signifie que le paramètre des fonctions appelées sera le même que l'argument passé par les appelants (pas la valeur, mais l'identité - la variable elle-même). Pass by value signifie que le paramètre appelé functions' sera une copie de l'argument passé des appelants. La valeur sera la même, mais l'identité de la variable est différente. Ainsi les changements à un paramètre fait par la fonction appelée dans un cas change l'argument passé et dans l'autre cas il suffit de modifier la valeur du paramètre dans la fonction appelée (qui n'est qu'une copie). Dans un rapide pressé:
- Java supporte uniquement la valeur de passage. Copie toujours les arguments, même si lors de la copie d'une référence à un objet, le paramètre dans la fonction appelée pointera vers le même objet et les changements à cet objet seront vus dans l'appelant. Comme cela peut prêter à confusion, ici est ce que Jon Skeet a à dire sur ce.
- c # supporte les valeurs pass by et pass by reference (mot-clé
ref
utilisé à l'appelant et appelé fonction). Jon Skeet a aussi une belle explication de ce ici . - c++ supporte les valeurs pass by et pass by reference (type de paramètre de référence utilisé à la fonction appelée). Vous trouverez une explication de ce ci-dessous.
Codes
puisque mon langage est C++, Je
// 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 mec assez bien les ongles:
beaucoup de réponses ici (et en particulier la réponse la plus contestée) sont inexactes dans les faits, car elles comprennent mal ce que "appel par référence" signifie réellement. Voici ma tentative de mettre les questions de droit.
TL; DR
en termes simples:
- appel par valeur signifie que vous avez passer valeurs comme "arguments de la fonction 1519620920"
- appel par la référence signifie que vous avez passer variables comme "arguments de la fonction 1519620920"
en termes métaphoriques:
- Appel par valeur est lorsque j'écris quelque chose sur un morceau de papier et le remettre à vous . C'est peut-être une URL, ou une copie de guerre et Paix. Peu importe ce qu'elle est, c'est sur une morceau de papier que j'ai donné à vous, et maintenant il est effectivement votre morceau de papier . Vous êtes maintenant libre de gribouiller sur ce bout de papier, ou d'utiliser ce bout de papier pour trouver quelque chose ailleurs et jouer avec, peu importe.
- Appel par la référence est lorsque je vous donne mon portable qui a quelque chose d'écrit en bas . Vous pouvez griffonner dans mon portable (peut-être que je veux que tu le fasses, peut-être pas), et après je garde mon carnet, avec tous les gribouillis que tu y as mis. Aussi, si ce que vous ou moi avons écrit il y a des informations sur comment trouver quelque chose ailleurs, vous ou moi pouvons aller là-bas et bidouiller avec cette information.
Ce "appel par valeur" et "appel par la référence" ne pas signifie
notez que ces deux concepts sont complètement indépendants et orthogonale du concept de types de référence (qui en Java est tous les types qui sont des sous-types de Object
, et en C# Tous les class
types), ou le concept de types de pointeur comme en C (qui sont sémantiquement équivalents aux "types de référence" de Java, simplement avec une syntaxe différente).
la notion de type de référence correspond à un URL: il s'agit à la fois d'une information et d'un référence (un pointeur , si vous voulez) vers d'autres informations. Vous pouvez avoir de nombreuses copies D'une URL à différents endroits, et ils ne changent pas le site Web auquel ils renvoient tous; si le site web est mis à jour alors chaque copie D'URL mènera toujours à l'information mise à jour. Inversement, changer L'URL à un endroit quelconque n'affectera aucune autre copie écrite de l'URL.
Note que C++ a une notion de " references "(par exemple int&
) qui est pas comme Java et C#'s" reference types", mais est comme"call by reference". Les "types de référence" de Java et C#, et tous les en Python, sont comme ce que C et C++ appellent des "types de pointeur" (par exemple int*
).
OK, voici l'explication plus longue et plus formelle.
Terminologie
pour commencer, je tiens à souligner quelques passages importants de la terminologie, pour aider à clarifier ma réponse et pour s'assurer que nous faisons tous référence aux mêmes idées lorsque nous utilisons des mots. (Dans la pratique, je crois que la grande majorité de la confusion au sujet de sujets comme ceux-ci découle de l'utilisation de mots d'une manière qui ne permet pas de communiquer pleinement le sens qui était prévu.)
pour commencer, voici un exemple dans un langage de type C d'une déclaration de fonction:
void foo(int param) { // line 1
param += 1;
}
Et voici un exemple d'appel de cette fonction:
void bar() {
int arg = 1; // line 2
foo(arg); // line 3
}
en utilisant cet exemple, je veux définir quelques bits importants de la terminologie:
-
foo
est une fonction déclarée sur la ligne 1 (Java insiste sur faire toutes les méthodes de fonctions, mais le concept est le même sans perte de généralité; C et C++ faire une distinction entre la déclaration et la définition lequel je n'entrerai pas ici) -
param
est un paramètre formel àfoo
, également déclaré à la ligne 1 -
arg
est une variable , plus précisément une variable locale de la fonctionbar
, déclarée et initialisée à la ligne 2 -
arg
est aussi une argument à un invocation defoo
sur la ligne 3
il y a deux ensembles de concepts très importants à distinguer ici. La première est valeur versus variable :
- Un valeur est le résultat de l'évaluation d'une expression dans la langue. Par exemple, dans la fonction
bar
ci-dessus, après la ligneint arg = 1;
, l'expressionarg
a la "valeur 1519580920"1
. - Un variable est un conteneur pour les valeurs . Une variable peut être mutable (c'est la valeur par défaut dans la plupart des langages de type C), en lecture seule (par exemple déclarée en utilisant Java
final
ou C#readonly
) ou profondément immuable (par exemple en utilisant C++'sconst
).
l'autre paire importante de concepts à distinguer est paramètre versus argument :
- Un paramètre (aussi appelé paramètre formel ) est un variable qui doit être fourni par l'appelant lors d'un appel de fonction.
- Un argument est un valeur qui est fourni par l'appelant d'une fonction à satisfaire un spécifique paramètre formel de la fonction
appel en valeur
In call by value , les paramètres formels de la fonction sont des variables qui sont nouvellement créées pour l'invocation de la fonction, et qui sont initialisées avec les valeurs de leur argument.
cela fonctionne exactement de la même manière que tout autre type de variables sont initialisées avec des valeurs. Par exemple:
int arg = 1;
int another_variable = arg;
ici arg
et another_variable
sont des variables complètement indépendantes -- leurs valeurs peuvent changer indépendamment les unes des autres. Cependant, au point où another_variable
est déclaré, Il est initialisé pour contenir la même valeur que arg
tient -- qui est 1
.
Puisqu'il s'agit de variables indépendantes, les changements à another_variable
n'affectent pas arg
:
int arg = 1;
int another_variable = arg;
another_variable = 2;
assert arg == 1; // true
assert another_variable == 2; // true
c'est exactement la même chose que la relation entre arg
et param
dans notre exemple ci-dessus, que je vais répéter ici pour la symétrie:
void foo(int param) {
param += 1;
}
void bar() {
int arg = 1;
foo(arg);
}
C'est exactement comme si nous avions écrit le code de cette façon:
// entering function "bar" here
int arg = 1;
// entering function "foo" here
int param = arg;
param += 1;
// exiting function "foo" here
// exiting function "bar" here
C'est-à-dire la caractéristique définissant ce que call by value signifie que le callee ( foo
dans ce cas) reçoit valeurs comme arguments, mais a sa propre variables pour ces valeurs des variables de l'appelant ( bar
dans ce cas).
pour revenir à ma métaphore ci-dessus, si je suis bar
et que vous êtes foo
, quand je vous appelle, je vous donne un morceau de papier avec un valeur écrit dessus. Vous appelez ce morceau de papier param
. Cette valeur est une copie de la valeur que j'ai écrite dans mon carnet (mes variables locales), dans une variable que j'appelle arg
.
(à part: selon le matériel et le système d'exploitation, il existe diverses conventions d'appel sur la façon dont vous appelez une fonction d'une autre. La convention d'appel est comme nous de décider si j'écris la valeur sur un morceau de mon papier, puis la main, ou si vous avez un morceau de papier que j'écris, ou si je l'écris sur le mur en face de nous deux. C'est également un sujet intéressant, mais qui va bien au-delà de cette réponse déjà longue.)
Appel par la référence
Dans appel par la référence , la fonction de paramètres formels sont tout simplement nouveaux noms pour les mêmes variables que l'appelant fournitures comme arguments.
pour revenir à notre exemple ci-dessus, c'est équivalent à:
// entering function "bar" here
int arg = 1;
// entering function "foo" here
// aha! I note that "param" is just another name for "arg"
arg /* param */ += 1;
// exiting function "foo" here
// exiting function "bar" here
depuis param
est juste un autre nom pour arg
-- c'est-à-dire, ils sont la même variable , les changements à param
sont reflétés dans arg
. C'est le moyen fondamental dans l'appel par référence diffère de l'appel par valeur.
très peu de langues supportent l'appel par référence, mais C++ peut le faire comme ceci:
void foo(int& param) {
param += 1;
}
void bar() {
int arg = 1;
foo(arg);
}
dans ce cas, param
n'a pas seulement la même valeur comme arg
, il fait est arg
(juste par un nom différent) et donc bar
peut observer que arg
a été incrémenté.
notez que c'est et non comment Java, JavaScript, C, Objective-C, Python, ou presque tout autre langage populaire fonctionne aujourd'hui. Cela signifie que ces langues sont et non appel par référence, elles sont appel par valeur.
Addendum: appel par le partage d'objets
si ce que vous avez est appel en valeur , mais la valeur réelle est un type de référence ou type de pointeur , alors la "valeur" elle-même n'est pas très intéressant (par exemple en C c'est juste un entier d'une taille spécifique à la plate-forme) -- ce qui est intéressant est ce que cette valeur pointe à .
si ce que ce type de référence (c'est-à-dire pointeur) indique est mutable alors un effet intéressant est possible: vous pouvez modifier la valeur pointée-à, et l'appelant peut observer des changements à la valeur pointée-à, même si l'appelant ne peut pas observer des changements au pointeur lui-même.
pour reprendre l'analogie de L'URL, le fait que je vous ai donné un copie de L'URL D'un site web n'est pas particulièrement intéressant si ce qui nous intéresse tous les deux est le site web, pas L'URL. Le fait que vous griffonnez sur votre copie de L'URL n'affecte pas ma copie de L'URL n'est pas une chose à laquelle nous nous soucions (et en fait, dans des langues comme Java et Python, la valeur "URL", ou de type de référence, ne peut pas être modifiée du tout, seule la chose pointée par elle peut).
Barbara Liskov, quand elle a inventé la programmation CLU langue (qui avait ces sémantique), rendu compte que les termes "appel par valeur" et "appel par la référence" n'étaient pas particulièrement utile pour décrire la sémantique de cette nouvelle langue. Elle invente donc un nouveau terme: appel par partage d'objet .
lors de la discussion des langues qui sont techniquement appel par valeur, mais où les types communs utilisés sont des types de référence ou de pointeur (c'est-à-dire: presque tous les impératifs modernes, orienté objet, ou multi-paradigme langage de programmation), je trouve que c'est beaucoup moins compliqué pour simplement éviter de parler de appel par valeur ou appel par la référence . S'en tenir à appel par partage d'objet (ou tout simplement appel par objet ) et personne ne sera confondu. :- )
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
}
avant de comprendre les 2 Termes, vous doit comprendre ce qui suit. Chaque objet, a 2 choses qui peuvent le distinguer.
- sa valeur.
- son adresse.
donc si vous dites employee.name = "John"
sachez qu'il y a 2 choses à propos de name
. Sa valeur est "John"
et aussi de son emplacement dans la mémoire qui est certains nombre hexadécimal peut-être comme ceci: 0x7fd5d258dd00
.
selon l'architecture du langage ou le type (classe, structure, etc.) de votre objet, vous seriez soit transférer "John"
ou 0x7fd5d258dd00
en Passant "John"
est connu comme le passage par valeur.
Le passage 0x7fd5d258dd00
est connu sous le nom de passage par référence. Toute personne pointant vers cet emplacement de mémoire aura accès à la valeur de "John"
.
pour plus d'informations, je vous recommande de lire à propos de déréférencement d'un pointeur et aussi Pourquoi choisir struct (type valeur) sur la classe (type référence)
la façon la plus simple d'obtenir ceci est sur un fichier Excel. Disons par exemple que vous avez deux nombres, 5 et 2 dans les cellules A1 et B1 en conséquence, et vous voulez trouver leur somme dans une troisième cellule, disons A2. Vous pouvez le faire de deux façons.
-
soit par en passant leurs valeurs à la cellule A2 en tapant = 5 + 2 dans cette cellule. Dans ce cas, si les valeurs des cellules A1 ou B1 changent, la somme en A2 reste le même.
-
ou par en passant les "références" des cellules A1 et B1 à la cellule A2 en tapant = A1 + B1 . Dans ce cas, si les valeurs des cellules A1 ou B1 changent, la somme de A2 change aussi.
Comparer: Valeur vs Référence
Passage Par Valeur Les paramètres locaux sont des copies des arguments originaux passés en changements apportés dans la fonction de ces variables n'affectent pas les originaux
Passage Par Référence Les paramètres locaux sont des références aux les arguments originaux sont passés. Modifications à ces variables dans la fonction originaux Aucune copie n'est faite, donc les frais généraux de copie (temps, stockage) sont sauvegardés
en passant par ref, vous passez essentiellement un indicateur à la variable. Pass by value vous passez une copie de la variable. Dans l'usage de base, cela signifie normalement passer par ref les changements à la variable seront vus être la méthode d'appel et passer par la valeur qu'ils ne seront pas.
Passage par valeur envoie une COPIE des données stockées dans la variable que vous spécifiez, passage par référence envoie un lien direct à la variable elle-même. Donc si vous passez une variable par référence et puis changez la variable à l'intérieur du bloc dans lequel vous l'avez passée, la variable originale sera changée. Si vous devez simplement passer par valeur, la variable d'origine ne pourra pas être modifié par le bloc, vous avez passé en, mais vous obtiendrez une copie de ce qu'elle contenait, au moment de l'appel.
une différence majeure entre eux est que les variables de type valeur stockent des valeurs, donc en spécifiant une variable de type valeur dans un appel de méthode passe une copie de la valeur de cette variable à la méthode. Les variables de type de référence stockent les références aux objets, de sorte que la spécification d'une variable de type de référence comme un argument passe à la méthode une copie de la référence réelle qui se réfère à l'objet. Même si la référence elle-même est passé par valeur, la méthode peut encore utiliser la référence qu'il reçoit pour interagir avec-et éventuellement modifier-l'objet original. De même, lorsque vous retournez des informations d'une méthode via un État de retour, la méthode retourne une copie de la valeur stockée dans une variable de type valeur ou une copie de la référence stockée dans une variable de type référence. Lorsqu'une référence est retournée, la méthode d'appel peut utiliser cette référence pour interagir avec l'objet référencé. Donc, en effet, les objets sont toujours passés par référence.
En c#, pour passer une variable par référence si l' appelé méthode peut modifier les variables, C# fournit des mots-clés ref et out. Appliquer le mot-clé ref à une déclaration de paramètre vous permet de passer une variable à une méthode par référence-la méthode appelée sera en mesure de modifier la variable originale dans l'appelant. Le mot-clé ref est utilisé pour les variables qui ont déjà été initialisées dans la méthode d'appel. Normalement, lorsqu'un appel de méthode contient une variable non initialisée comme argument, le compilateur génère une erreur. Précédant un paramètre avec keyword out crée un paramètre de sortie. Cela indique au compilateur que l'argument sera passé dans la méthode appelée par la référence et que la méthode appelée sera attribuer une valeur à la variable d'origine en l'appelant. Si la méthode n'attribue pas de valeur au paramètre de sortie dans chaque chemin d'exécution possible, le compilateur génère une erreur. Cela empêche également le compilateur de générer un message d'erreur pour une variable non initialisée est passé comme argument à une méthode. Une méthode ne peut retourner qu'une seule valeur à son appelant via une instruction de retour, mais peut retourner de nombreuses valeurs en spécifiant plusieurs paramètres de sortie (ref et/ou out).
voir c# de discussion et des exemples ici texte du lien
Pass by value - la fonction copie la variable et fonctionne avec une copie(de sorte qu'elle ne change rien dans la variable originale)
Passage par référence - La fonction utilise la variable d'origine, si vous modifiez la variable dans la fonction, les changements dans la variable d'origine.
exemple (copier et utiliser / essayer vous-même et voir):
#include <iostream>
using namespace std;
void funct1(int a){ //pass-by-value
a = 6; //now "a" is 6 only in funct1, but not in main or anywhere else
}
void funct2(int &a){ //pass-by-reference
a = 7; //now "a" is 7 both in funct2, main and everywhere else it'll be used
}
int main()
{
int a = 5;
funct1(a);
cout<<endl<<"A is currently "<<a<<endl<<endl; //will output 5
funct2(a);
cout<<endl<<"A is currently "<<a<<endl<<endl; //will output 7
return 0;
}
Keep it simple, jette un coup d'oeil. Les murs de texte peut être une mauvaise habitude.
exemples:
class Dog
{
public:
barkAt( const std::string& pOtherDog ); // const reference
barkAt( std::string pOtherDog ); // value
};
const &
est généralement préférable. Vous n'encourez pas la pénalité de construction et de destruction. Si la référence n'est pas const, votre interface suggère qu'elle changera les données transmises.
bref, la valeur transmise est ce qu'elle est et la référence transmise est où elle est.
si votre valeur est VAR1 = " Happy Guy!", vous ne verrez que les "Heureux les Gars!". Si VAR1 change en " Happy Gal!"vous ne savez pas qui. S'il est passé par référence, et que VAR1 change, vous le ferez.
par définition, passer par valeur signifie que vous faites une copie en mémoire de la valeur réelle du paramètre qui est passée, une copie du contenu du paramètre réel. Utilisez la valeur pass by lorsque vous "utilisez" seulement le paramètre pour un certain calcul, sans le modifier pour le programme client.
Dans le passage par référence (aussi appelé passage par adresse), une copie de l'adresse du paramètre effectif est stocké. Utiliser les passer par référence lorsque vous modifiez l' paramètre transmis par le programme client.
passer par la valeur signifie Comment passer la valeur à une fonction en faisant usage des arguments. dans la valeur de passage, nous copions les données stockées dans la variable que nous spécifions et il est plus lent que passer par la référence bcse t il les données sont copiées . de nous faisons des changements dans les données copiées les données originales ne sont pas affectées. nd in pass by refernce ou pass by address nous envoyons un lien direct à la variable elle-même . ou en passant un pointeur sur une variable. il est plus rapide bcse moins de temps est consommé
si vous ne voulez pas changer la valeur de la variable d'origine après l'avoir passée dans une fonction, la fonction doit être construite avec un paramètre " pass by value ".
Alors que la fonction aura SEULEMENT la valeur, mais pas l'adresse de la variable. Sans l'adresse de la variable, le code à l'intérieur de la fonction ne peut pas changer la valeur de la variable vue de l'extérieur de la fonction.
mais si vous souhaitez donner à la fonction de l' *possibilité de changer la valeur de la variabl*e que vu de l'extérieur, vous devez utiliser passage par référence . Comme la valeur et l'adresse (de référence) sont transmises et disponible à l'intérieur de la fonction.
Voici un exemple qui démontre les différences entre passer par la valeur - valeur de pointeur-référence :
void swap_by_value(int a, int b){
int temp;
temp = a;
a = b;
b = temp;
}
void swap_by_pointer(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void swap_by_reference(int &a, int &b){
int temp;
temp = a;
a = b;
b = temp;
}
int main(void){
int arg1 = 1, arg2 = 2;
swap_by_value(arg1, arg2);
cout << arg1 << " " << arg2 << endl; //prints 1 2
swap_by_pointer(&arg1, &arg2);
cout << arg1 << " " << arg2 << endl; //prints 2 1
arg1 = 1; //reset values
arg2 = 2;
swap_by_reference(arg1, arg2);
cout << arg1 << " " << arg2 << endl; //prints 2 1
}
la méthode de "passage par référence" a une limitation importante . Si un paramètre est déclaré comme passé par la référence (donc il est précédé par le signe&) son correspondant paramètre réel doit être une variable .
An paramètre réel se référant à" passé par la valeur "paramètre formel peut être une expression en général, il est donc permis d'utiliser non seulement une variable, mais aussi un littéral ou même une fonction résultat de l'invocation.
La fonction n'est pas en mesure de placer une valeur dans autre chose qu'une variable. Il ne peut pas assigner une nouvelle valeur à un littéral ou forcer une expression à changer son résultat.
PS: Vous pouvez également consulter Dylan Beattie Répondez dans le fil courant qui l'explique en mots simples.