2009-06-17 7 views
0

Disons que j'ai une classe:Comment éviter d'appeler explicitement un constructeur lors du passage d'un objet temporaire par référence en C++?

class String 
{ 
public: 
    String(char *str); 
}; 

Et deux fonctions:

void DoSomethingByVal(String Str); 
void DoSomethingByRef(String &Str); 

Si je l'appelle DoSomethingByVal comme ceci:

DoSomethingByVal("My string"); 

le compilateur chiffres que devrait créer un objet String temporaire et appelle le constructeur char *.

Cependant, si j'essaie d'utiliser DoSomethingByRef de la même manière, j'obtiens un message d'erreur "Impossible de convertir le paramètre from 'char *' en 'String &'".

Au lieu de cela, je dois créer explicitement une instance:

DoSomethingByRef(String("My string")); 

qui peut obtenir preety ennuyeux.

Est-il possible d'éviter cela?

Répondre

9

Vous devez passer par référence const:

Pour:

void DoSomethingByVal(String Str); 

Dans cette situation, le compilateur crée d'abord une variable temporaire. La variable temporaire est ensuite copiée dans le paramètre.

Pour:

void DoSomethingByRef(String const& Str); 

Dans cette situation, le compilateur crée une variable temporaire. Mais les variables temporaires ne peuvent pas être liées à une référence, elles ne peuvent être liées qu'à une référence const, de sorte que votre fonction d'origine ne peut pas être appelée. Notez que le constructeur d'objets std :: string prend une référence const est le paramètre du constructeur de copie et c'est pourquoi la première version fonctionne comme le temporaire est lié au paramètre de référence const du constructeur de copie uniquement.

+0

Merci. Ça fait l'affaire :) –

2

Hmm, je ne sais pas si

void DoSomethingByRef(String &Str); 
DoSomethingByRef(String("My string")); 

serait en fait la compilation. Un rvalue ne peut pas se lier à une référence à non-const (car un ref à non-const indique que vous allez modifier la valeur, et il ne serait pas logique de modifier un temporaire). Etes-vous sûr que vous ne faites pas:

String str("My string"); 
DoSomethingByRef(str); 

Si vous voulez DoSomethingByVal prendre un rvalue, le paramètre doit être une référence à const:

void DoSomethingByRef(const String &Str); 
+4

C'est MSVC++ cerveau-mort qui permet d'accepter une valeur. Bien sûr, ce n'est pas valide, comme vous le dites. –

+0

DoSomethingByRef (String ("Ma chaîne")); compilerait sur vc2008 –

+0

@hammer: revenir à litb commentaire: "C'est MSVC++ cerveau-mort ..." :) –

0

Marque:

DoSomethingByRef (chaîne de caractères const & str);

0

"Ma chaîne" n'est pas une chaîne, c'est un c-string, un char *, si vous voulez. Vous devez mettre ce c-string dans un objet String, et ALORS vous pouvez passer le nouvel objet String par référence.

Un autre point, vous passez déjà un caractère * ... qui est assez léger, juste un pointeur. Pourquoi s'inquiéter de passer un nouvel objet par référence? Juste allouer un nouvel objet à l'intérieur de ce constructeur à partir du tas et copiez le c-string dans celui-ci.

Questions connexes