c++ return-value sentinel

c++ - Devuelve un objeto "NULO" si no se encuentra el resultado de la búsqueda



return-value sentinel (8)

Soy bastante nuevo en C ++, así que tiendo a diseñar con muchos Java-ismos mientras estoy aprendiendo. De todos modos, en Java, si tuviera clase con un método de "búsqueda" que devolviera un objeto T de una Collection< T > que coincidiera con un parámetro específico, devolvería ese objeto y, si el objeto no se encontraba en la colección, devolvería null . Luego, en mi función de llamada, simplemente verificaría if(tResult != null) { ... }

En C ++, estoy descubriendo que no puedo devolver un valor null si el objeto no existe. Solo quiero devolver un ''indicador'' de tipo T que notifica a la función de llamada que no se ha encontrado ningún objeto. No quiero lanzar una excepción porque no es realmente una circunstancia excepcional.

Así es como se ve mi código en este momento:

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; }

¿Cómo puedo cambiarlo para poder darle ese tipo de marcador?


Como has descubierto, no puedes hacerlo de la manera que lo has hecho en Java (o C #). Aquí hay otra sugerencia, podría pasar la referencia del objeto como argumento y devolver el valor de bool. Si el resultado se encuentra en su colección, puede asignarlo a la referencia que se pasa y devolver ''verdadero''; de lo contrario, devolver ''falso''. Por favor considere este código.

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 función anterior tiene que encontrar el Operador contra la clave ''token'', si encuentra la que devuelve verdadera y asignar el valor al parámetro Operador & op.

El código de la persona que llama para esta rutina se ve así

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


En C ++, las referencias no pueden ser nulas. Si desea devolver nulo de forma opcional si no se encuentra nada, debe devolver un puntero, no una referencia:

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

De lo contrario, si insiste en regresar por referencia, debe lanzar una excepción si el atributo no se encuentra.

(Por cierto, estoy un poco preocupado de que tu método sea const y devuelva un atributo no const . Por razones filosóficas, te sugiero que const Attr * . Si también puedes modificar este atributo, puedes sobrecargarlo con un método no const devolviendo un atributo no const también).


Hay varias respuestas posibles aquí. Quieres devolver algo que pueda existir. Aquí hay algunas opciones, que van desde mi menos preferido hasta el más preferido:

  • Devuelve por referencia y la señal no puede encontrar por excepción.

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

Es probable que no encontrar atributos sea una parte normal de la ejecución, y por lo tanto no muy excepcional. El manejo de esto sería ruidoso. No se puede devolver un valor nulo porque su comportamiento indefinido tiene referencias nulas.

  • Regreso por puntero

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

Es fácil olvidarse de comprobar si un resultado de getAttribute sería un puntero no NULL y es una fuente fácil de errores.

  • Use Boost.Optional

    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 impulso :: opcional significa exactamente lo que está sucediendo aquí, y tiene métodos fáciles para inspeccionar si se encontró dicho atributo.

Nota al margen: std :: opcional fue votado recientemente en C ++ 17, por lo que esto será algo "estándar" en el futuro cercano.


La razón por la que no puede devolver NULL aquí es porque ha declarado su tipo de devolución como Attr& . El final hace que el valor de retorno sea una "referencia", que básicamente es un puntero garantizado que no debe ser nulo a un objeto existente. Si desea poder devolver nulo, cambie Attr& Attr* .


No puede devolver NULL porque el tipo de devolución de la función es una reference objeto y no un pointer .


Puede crear fácilmente un objeto estático que represente un retorno NULO.

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; };

Y en algún lugar en un archivo fuente:

static Attr AttrNull;


Puedes intentar esto:

return &Type();