2009-10-05 9 views
2

J'ai défini la classe suivante:Y a-t-il un avantage à utiliser un argument de référence dans cette fonction?

class Action 
{ 
    public: 
    Action(){ _bAllDone = false; } 

    void AddMove(Move & m); 
    private: 
     std::deque<Move> _todo; 
     bool _bAllDone; 
}; 

Le membre AddMove est défini comme suit:

void Action::AddMove(Move & m) 
{ 
    _todo.push_back(m); 
} 

J'ai noté que, sans l'argument de référence à cette fonction, le constructeur copie a été appelée deux fois, whereeas avec un argument de référence, il n'a été appelé qu'une seule fois. Est-ce que appeler un constructeur de copie seulement une fois au lieu de deux fois une bonne raison d'utiliser un argument de référence?

Répondre

17

La classe deque dans STL est supposée conserver une copie de l'élément que vous transmettez à sa méthode push_back. C'est de là que vient un constructeur de copie. Si vous supprimez la référence dans addMove(), vous obtiendrez d'abord une copie du paramètre (et donc une invocation du constructeur de copie), puis vous obtiendrez une seconde copie lorsque vous repousserez.

La double invocation du constructeur de copie est inutile, la référence est donc préférable. Cependant, vous devez déclarer le paramètre addMove() en tant que référence const, pour indiquer à l'appelant que l'élément ne sera pas modifié. Sous une telle assurance (en supposant que vous ne le cassez pas), il est prudent de passer l'objet par référence sans se soucier et sans payer la pénalité d'une copie d'objet.

+0

Une bonne réponse, et +1 pour le passer comme const. –

+2

Une autre raison importante (je dirais la raison la plus importante, IMO, si votre code est déjà conçu pour ne pas modifier la référence) pour passer par référence à const est de permettre aux temporaires d'être acceptés comme paramètres (par exemple 'action.AddMove (Move (/ * ... * /)); 'est valide si' AddMove' prend un 'const Move &', mais est invalide s'il ne prend qu'un 'Move &') – GRB

4

Cela me semble être un gros avantage. Les choses pourraient devenir très lentes si vous effectuez de nombreux ajouts itératifs. La quantité réelle de travail dépend de la définition de Move et de son constructeur de copie. De petits changements pourraient avoir de graves conséquences sur les performances. Mordre dans les deux sens, en passant par la copie serait encore deux fois plus de travail.

L'effet global dépend de la quantité de traitement totale dépensée pour cette opération. Faites-le une fois, vous ne remarquerez jamais; faites-le quelques milliers de fois, et cela peut être significatif. Cependant, en règle générale, évitez de copier des données où vous pouvez les référencer en toute sécurité, d'autant plus qu'il n'y a pas de problème de clarté ou de complexité particulier - il est aussi facile de faire vite que de ralentir, alors pourquoi faites-le lentement?

0

Il doit être une référence, sinon vous serez encourir une copie de l'argument inutile (et potentiellement incorrect). Il devrait également être const, sinon vous restreindrez inutilement vos appelants.

Notez également que les noms avec un trait de soulignement principal sont réservés à l'implémentation du langage, de sorte que votre programme est actuellement "indéfini".

HTH

Questions connexes