Je pense que beaucoup de confusion est généré par le fait de ne pas faire ce que l'on entend par passé par référence. Quand certaines personnes disent passage par référence , ils signifient généralement pas l'argument lui-même, mais plutôt l'objet référencé. Certains autres disent que le passage par référence signifie que l'objet ne peut pas être modifié dans le destinataire de l'appel. Exemple:
struct Object {
int i;
};
void sample(Object* o) { // 1
o->i++;
}
void sample(Object const& o) { // 2
// nothing useful here :)
}
void sample(Object & o) { // 3
o.i++;
}
void sample1(Object o) { // 4
o.i++;
}
int main() {
Object obj = { 10 };
Object const obj_c = { 10 };
sample(&obj); // calls 1
sample(obj) // calls 3
sample(obj_c); // calls 2
sample1(obj); // calls 4
}
Certaines personnes prétendent que le 1 et le 3 sont passer par référence, tandis que 2 serait le passage par valeur. Un autre groupe de gens disent tous, mais le dernier est le passage par référence, parce que l'objet lui-même n'est pas copié.
Je voudrais attirer une définition de ce là ce que je demande à passer par référence. Un aperçu général sur il peut être trouvé ici: Différence entre le passage par référence et le passage par valeur . Tous les mais la première et la dernière sont passage par référence:
sample(&obj);
// yields a `Object*`. Passes a *pointer* to the object by value.
// The caller can change the pointer (the parameter), but that
// won't change the temporary pointer created on the call side (the argument).
sample(obj)
// passes the object by *reference*. It denotes the object itself. The callee
// has got a reference parameter.
sample(obj_c);
// also passes *by reference*. the reference parameter references the
// same object like the argument expression.
sample1(obj);
// pass by value. The parameter object denotes a different object than the
// one passed in.
Je vote pour la définition suivante:
Un argument (1.3.1) est passé par référence si et seulement si le paramètre correspondant de la fonction appelée est le type de référence et la valeur de référence se lie directement à l'argument de l'expression (8.5.3/4). Dans tous les autres cas, nous avons à faire avec le passage par valeur.
Cela signifie que suivant est le passage par valeur:
void f1(Object const& o);
f1(Object()); // 1
void f2(int const& i);
f2(42); // 2
void f3(Object o);
f3(Object()); // 3
Object o1; f3(o1); // 4
void f4(Object *o);
Object o1; f4(&o1); // 5
1
est le passage par valeur, car il n'est pas directement lié. La mise en œuvre peut copier le temporaire et le lier ensuite que temporaire à la référence. 2
est le passage par valeur, parce que la mise en œuvre initialise une temporaire de la littéralité et se lie alors à la référence. 3
est le passage par valeur, parce que le paramètre n'a pas de type de référence. 4
est le passage par valeur pour la même raison. 5
est le passage par valeur, parce que le paramètre n'a pas de type de référence. Les cas suivants sont passage par référence (par les règles de 8.5.3/4 et d'autres):
void f1(Object *& op);
Object a; Object *op1 = &a; f1(op1); // 1
void f2(Object const& op);
Object b; f2(b); // 2
struct A { };
struct B { operator A&() { static A a; return a; } };
void f3(A &);
B b; f3(b); // passes the static a by reference