Retourne un object “NULL” si le résultat de la recherche est introuvable

Je suis assez nouveau en C ++, donc j’ai tendance à concevoir avec beaucoup de Java-isms pendant que j’apprends. Quoi qu’il en soit, en Java, si j’avais une classe avec une méthode ‘search’ qui retournerait un object T provenant d’une Collection qui correspondait à un paramètre spécifique, je retournerais cet object et si l’object n’était pas trouvé dans la collection, je renverrait null . Ensuite, dans ma fonction d’appel, je vérifierais simplement if(tResult != null) { ... }

En C ++, je découvre que je ne peux pas retourner une valeur null si l’object n’existe pas. Je veux juste retourner un “indicateur” de type T qui notifie à la fonction appelante qu’aucun object n’a été trouvé. Je ne veux pas lancer une exception parce que ce n’est pas vraiment une circonstance exceptionnelle.

Voici à quoi ressemble mon code en ce moment:

 class Node { Attr& getAtsortingbute(const ssortingng& atsortingbute_name) const { //search collection //if found at i return atsortingbutes[i]; //if not found return NULL; // what should this be? } private: vector atsortingbutes; } 

Comment puis-je le changer pour que je puisse donner ce genre de marqueur?

En C ++, les références ne peuvent pas être nulles. Si vous voulez renvoyer éventuellement null si rien n’est trouvé, vous devez renvoyer un pointeur, pas une référence:

 Attr *getAtsortingbute(const ssortingng& atsortingbute_name) const { //search collection //if found at i return &atsortingbutes[i]; //if not found return nullptr; } 

Sinon, si vous insistez pour retourner par référence, vous devriez alors lancer une exception si l’atsortingbut n’est pas trouvé.

(Soit dit en passant, je suis un peu inquiet de votre méthode étant const et de renvoyer un atsortingbut non const . Pour des raisons philosophiques, je suggère de renvoyer const Attr * . Si vous souhaitez également modifier cet atsortingbut, vous pouvez surcharger avec une méthode non const renvoyant également un atsortingbut non const .)

Il y a plusieurs réponses possibles ici. Vous voulez retourner quelque chose qui pourrait exister. Voici quelques options, allant du moins préféré au plus préféré:

  • Retour par référence, et signal ne peut pas trouver par exception.

     Attr& getAtsortingbute(const ssortingng& atsortingbute_name) const { //search collection //if found at i return atsortingbutes[i]; //if not found throw no_such_atsortingbute_error; } 

Il est probable que ne pas trouver d’atsortingbuts est une partie normale de l’exécution, et donc pas très exceptionnelle. La manipulation pour cela serait bruyante. Une valeur null ne peut pas être renvoyée car son comportement non défini comporte des références nulles.

  • Retour par pointeur

     Attr* getAtsortingbute(const ssortingng& atsortingbute_name) const { //search collection //if found at i return &atsortingbutes[i]; //if not found return nullptr; } 

Il est facile d’oublier de vérifier si un résultat de getAtsortingbute serait un pointeur non NULL et constitue une source facile de bogues.

  • Utilisez Boost.Optional

     boost::optional getAtsortingbute(const ssortingng& atsortingbute_name) const { //search collection //if found at i return atsortingbutes[i]; //if not found return boost::optional(); } 

Un boost :: optional signifie exactement ce qui se passe ici et a des méthodes simples pour vérifier si un tel atsortingbut a été trouvé.


Side note: std :: optionnel a été récemment voté en C ++ 17, donc ce sera une chose “standard” dans un avenir proche.

Vous pouvez facilement créer un object statique qui représente un retour NULL.

 class Attr; extern Attr AttrNull; class Node { .... Attr& getAtsortingbute(const ssortingng& atsortingbute_name) const { //search collection //if found at i return atsortingbutes[i]; //if not found return AttrNull; } bool IsNull(const Attr& test) const { return &test == &AttrNull; } private: vector atsortingbutes; }; 

Et quelque part dans un fichier source:

 static Attr AttrNull; 

Si vous voulez une NULL retour NULL , vous devez utiliser des pointeurs au lieu de références.

Les références ne peuvent elles-mêmes être NULL .

(Note aux futures affiches de commentaires: Oui, vous pouvez avoir l’adresse d’une référence soit NULL si vous essayez vraiment).

Voir ma réponse ici pour une liste des différences entre les références et les pointeurs .

Comme vous l’avez compris, vous ne pouvez pas le faire comme vous l’avez fait en Java (ou en C #). Voici une autre suggestion, vous pouvez passer la référence de l’object en tant qu’argument et renvoyer la valeur bool. Si le résultat est trouvé dans votre collection, vous pouvez l’assigner à la référence transmise et renvoyer «true», sinon renvoyer «false». Veuillez considérer ce code.

 typedef std::map OPERATORS_MAP; bool OperatorList::tryGetOperator(ssortingng token, Operator& op) { bool val = false; OPERATORS_MAP::iterator it = m_operators.find(token); if (it != m_operators.end()) { op = it->second; val = true; } return val; } 

La fonction ci-dessus doit trouver l’opérateur par rapport à la clé ‘token’, si elle trouve celle qui est renvoyée true et affecter la valeur au paramètre Opérateur & op.

Le code de l’appelant pour cette routine ressemble à ceci

 Operator opr; if (OperatorList::tryGetOperator(strOperator, opr)) { //Do something here if true is returned. } 

La raison pour laquelle vous ne pouvez pas retourner la valeur NULL est que vous avez déclaré votre type de retour comme Attr& . Le trailing & rend la valeur de retour une “référence”, qui est fondamentalement un pointeur garanti à ne pas être nul sur un object existant. Si vous voulez pouvoir renvoyer null, modifiez Attr& to Attr* .

Vous ne pouvez pas retourner NULL car le type de retour de la fonction est une reference object et non un pointer .

Vous pouvez essayer ceci:

 return &Type();