La conversion implicite: référence const vs référence non-const vs non-référence
-
11-10-2019 - |
Question
Considérez ce code,
struct A {};
struct B { B(const A&) {} };
void f(B)
{
cout << "f()"<<endl;
}
void g(A &a)
{
cout << "g()" <<endl;
f(a); //a is implicitly converted into B.
}
int main()
{
A a;
g(a);
}
compiles bien, fonctionne très bien. Mais si je change f(B)
à f(B&)
, il ne compile pas . Si je vous écris f(const B&)
, encore compile bien , fonctionne très bien. Pourquoi la raison et la raison?
Résumé:
void f(B); //okay
void f(B&); //error
void f(const B&); //okay
Je voudrais entendre raisons, justification et référence (s) de la spécification du langage, pour chacun de ces cas. Bien sûr, les signatures de fonction ne sont pas elles-mêmes incorrectes. Au contraire A
implicitement convertis en B
et const B&
, mais pas en B&
, et qui provoque l'erreur de compilation.
La solution
Je voudrais entendre raisons, justification et référence (s) de la spécification du langage
est La conception et l'évolution de C ++ suffisant?
J'ai fait une grave erreur, mais, en permettant une référence non-const à initialiser par un non-lvalue [ Commentaire de moi: ce libellé est imprécis !]. Par exemple:
void incr(int& rr) { ++rr; } void g() { double ss = 1; incr(ss); // note: double passed, int expected // (fixed: error in release 2.0) }
En raison de la différence dans le type de la
int&
ne peut pas se référer à ladouble
passé si temporaire a été généré pour tenir unint
initialisé par la valeur dess
. Ainsi,incr()
modifié le temporaire, et le résultat n'a pas été réfléchie à la fonction appelant [ Souligné par l'auteur ].
Pensez-y: Le point entier de l'appel par référence est que le client passe des choses qui sont modifiées par la fonction, et après le retour de la fonction, le client doit être en mesure d'observer les changements .
Autres conseils
Le problème est que la conversion implicite à partir d'un à un objet B donne un rvalue. Les références non const ne peuvent se lier à lvalues.
Si B avait un constructeur par défaut, vous obtiendrez le même comportement si vous changez l'appel f(a)
à f(B())
.
-
litb fournit une excellente réponse à ce qui est une lvalue: Stack Overflow - souvent utilisé des termes rarement définis: lvalue
GotW # 88: un candidat pour le « plus important const »
Stack Overflow - Comment venir ne peut pas se lier à une référence non-const à un objet temporaire?
-
Pour expliquer avec des références à la norme la façon dont ces appels de fonctions échouent ou réussissent serait trop long. L'important est de savoir comment B& b = a;
échoue alors que const B& b = a;
ne manque pas.
(du projet n1905)
La mention de type « CV1 T1 » est initialisé par une expression de type « T2 CV2 » comme suit:
- [ est une lvalue et est soit référence compatible ou implicitement convertible en une lvalue d'un type compatible de référence ... ]
-. Dans le cas contraire, la référence est à un type de const non-volatile (par exemple, CV1 est const)
est un cas où quelque chose est convertible à un lvalue de référence type compatible.