Retourner un objet "NULL" si le résultat de la recherche n'est pas trouvé

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 class avec une méthode 'search' qui retournerait un objet T à partir d'un Collection< T > qui correspond à un paramètre spécifique, je retournerais cet objet et si l'objet n'était pas trouvé dans la collection, je retournerais null . Ensuite, dans ma fonction d'appel, je vérifierais simplement if(tResult != null) { ... }

En C++, je suis la recherche que je ne peux pas retourner un null valeur si l'objet n'existe pas. Je veux simplement retourner un "indicateur" de type T qui avertit la fonction d'appel qu'aucun objet n'a été trouvé. Je ne veux pas faire d'exception parce que ce n'est pas vraiment une circonstance exceptionnelle.

voici à quoi ressemble mon code en ce moment:

class Node {
    Attr& getAttribute(const string& attribute_name) const {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return NULL; // what should this be?
    }

private:
    vector<Attr> attributes;
}

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

85
demandé sur Nic Hartley 2010-04-14 20:41:46

8 réponses

en C++, les références ne peuvent pas être nulles. Si vous voulez retourner optionnellement null si rien n'est trouvé, vous devez retourner un pointeur, pas une référence:

Attr *getAttribute(const string& attribute_name) const {
   //search collection
   //if found at i
        return &attributes[i];
   //if not found
        return nullptr;
}

Sinon, si vous insistez pour revenir par référence, alors vous devriez jeter une exception si l'attribut n'est pas trouvé.

(soit dit en passant, je suis un peu inquiet que votre méthode soit const et renvoie un attribut non - const . Pour des raisons philosophiques, je suggérerais le retour "à la 151930920" . Si vous voulez aussi modifier cet attribut, vous pouvez surcharger avec une méthode non- const retournant aussi un attribut non- const .)

59
répondu Jesse Beder 2014-11-09 23:04:16

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

  • Retour par référence et le signal peut pas trouver par exception à la règle.

    Attr& getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            throw no_such_attribute_error;
    }

il est probable que ne pas trouver les attributs est une partie normale de l'exécution, et donc pas très exceptionnel. La manipulation pour cela serait bruyant. Une valeur nulle ne peut pas être retournée parce que c'est un comportement non défini d'avoir des références nulles.

  • Retour par pointeur

    Attr* getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return &attributes[i];
       //if not found
            return nullptr;
    }

il est facile d'oublier de vérifier si un résultat de getAttribute serait un pointeur non nul, et est une source facile de bogues.

  • Utiliser Coup De Pouce.Facultatif

    boost::optional<Attr&> getAttribute(const string& attribute_name) const 
    {
       //search collection
       //if found at i
            return attributes[i];
       //if not found
            return boost::optional<Attr&>();
    }

un boost::optionnel signifie exactement ce qui se passe ici, et dispose de méthodes faciles pour vérifier si un tel attribut a été trouvé.


note de Côté: std::facultatif a été récemment voté en C++17, ce sera donc un "standard" de la chose dans un avenir proche.

50
répondu Kaz Dragon 2016-07-06 09:46:44

vous pouvez facilement créer un objet statique qui représente un retour nul.

class Attr;
extern Attr AttrNull;

class Node { 
.... 

Attr& getAttribute(const string& attribute_name) const { 
   //search collection 
   //if found at i 
        return attributes[i]; 
   //if not found 
        return AttrNull; 
} 

bool IsNull(const Attr& test) const {
    return &test == &AttrNull;
}

 private: 
   vector<Attr> attributes; 
};

et quelque part dans un fichier source:

static Attr AttrNull;
22
répondu Mark Ransom 2010-04-14 17:22:00

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

les références ne peuvent pas être NULL .

(Note aux posters de commentaires futurs: Oui, vous pouvez avoir L'adresse D'une référence être NULL si vous vraiment essayer de).

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

3
répondu Brian R. Bondy 2017-05-23 11:33:26

comme vous avez compris que vous ne pouvez pas le faire comme vous l'avez fait en Java (ou C#). Voici une autre suggestion, vous pourriez passer dans la référence de l'objet comme argument et retour bool valeur. Si le résultat est trouvé dans votre collection, vous pouvez l'assigner à la référence passée et retourner ‘true’, sinon retourner ‘false’. Veuillez considérer ce code.

typedef std::map<string, Operator> OPERATORS_MAP;

bool OperatorList::tryGetOperator(string 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 contre la touche 'token', si elle trouve celui qu'il renvoie true et attribue la valeur au paramètre Operator & 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.
}
2
répondu A.B. 2016-02-20 13:22:49

la raison pour laquelle vous ne pouvez pas retourner NULL ici est que vous avez déclaré votre type de retour comme Attr& . La suite & fait de la valeur de retour une" référence", qui est fondamentalement un pointeur garanti-non-nul à un objet existant. Si vous voulez pouvoir retourner null, changez Attr& en Attr* .

1
répondu JSBձոգչ 2010-04-14 16:49:18

vous ne pouvez pas retourner NULL parce que le type de retour de la fonction est un objet reference et non un pointer .

0
répondu codaddict 2010-04-14 16:45:03

Vous pouvez essayer ceci:

return &Type();
-4
répondu Created 2015-12-14 21:10:27