Pregunta

Estoy trabajando en C ++ y necesito saber si un valor escalar (por ejemplo, un double) es " definido " o no. También necesito poder & Quot; undef & Quot; si es necesario:

class Foo {
public:
    double get_bar();

private:
    double bar;
    void calculate_bar() {
        bar = something();
    }
};

double Foo::get_bar() {
    if ( undefined(bar) )
        calculate_bar();
    return bar;
}

¿Es posible en C ++?

Gracias

¿Fue útil?

Solución

Como dicen las otras respuestas, C ++ no tiene este concepto. Sin embargo, puede solucionarlo fácilmente.

O bien puede tener un valor indefinido al que inicializa la barra en el constructor, generalmente -1.0 o algo similar.

Si sabe que Calculate_bar nunca devuelve valores negativos, puede implementar la función indefinida como un control para < 0.0.

Una solución más general es tener un bool que diga si la barra está definida pero que se inicializó en falso en el constructor y cuando la configura por primera vez la cambia a verdadera. boost :: opcional hace esto en una elegante forma de plantilla.

Así es como se vería el ejemplo de código que tiene.

class Foo {
public:
    double get_bar();
    Foo() : barDefined(false) {}
private:
    double bar;
    bool barDefined;
    void calculate_bar() {
        bar = something();
    }
};

double Foo::get_bar() {
    if ( barDefined == false ) {
        calculate_bar();
        barDefined = true;
    }
    return bar;
}

Otros consejos

Como otros señalaron, no hay nada como un & "; indefinido &"; estado. Pero es posible que desee consultar boost.optional

Si quiere decir en tiempo de ejecución, no existe tal cosa. Si bar nunca se inicializa, tendrá los bits aleatorios que estén allí, dependiendo de cómo se asigne el objeto (algunos asignadores inicializarán la nueva memoria a cero).

editar: depende del programador manejar el estado del objeto en constructores y / o métodos de inicialización manual como init()

¿Por qué no mantener un indicador separado que se inicializa en falso y luego se establece en verdadero cuando se calcula la barra? Luego puede ser 'undefed' configurando la bandera a falso nuevamente.

if(!isBarValid)
{
    calculateBar();
    isBarValid = true;
}
return bar;

C ++ no tiene un & "; indefinido &"; estado para tipos primitivos. El más cercano disponible para flotante / doble sería NAN, pero eso realmente tiene un significado diferente.

Esto no es posible en C / C ++, las primitivas siempre tendrán un valor asignado (principalmente basura, lo que sea que haya estado en ese punto en la memoria anterior, a menos que se asigne explícitamente en la declaración). Es común tener un valor de marcador de posición (es decir, 0 para punteros) que denota no utilizado, sin embargo, estos también deben asignarse explícitamente. Si su doble puede tomar cualquier valor, le sugiero que coloque un booleano al lado, asignado a falso inicialmente, y pruebe / configure ese cuando quiera hacer su cálculo.

Debe hacerlo utilizando un booleano adicional.

Para implementar usando un booleano adicional, puede probar una lógica como la siguiente plantilla:

template<typename T>
struct Defined
{
 bool defined;
 T value;
 Defined() : defined(false) {}
 Defined(const T& value_) : defined(true), value(value_) {}
 ... and perhaps other operators here ...
 ... to make this behave even more like a T ...
};

Puede probar el Construir en el idioma de primer uso y escriba get_bar() de esta manera:

double & get_bar()
{
    static double *bar = new double(something());
    return *bar;
}

Cuando llame a bar, hará double & por usted si nadie lo ha pedido todavía. Cualquier llamada posterior solo devolverá <=>. Como dice la página vinculada, esto técnicamente no pierde memoria porque el sistema operativo la recuperará cuando el programa salga.

ACTUALIZACIÓN:

Cambió el valor de retorno a <=> para permitirle modificar <=>.

Inicialice bar a algún valor que nunca puede ocurrir cuando llama a la función something() en el constructor.

Por ejemplo:

Foo(): bar(-1)
{
}

Luego verifique el valor -1 en la función get_bar.

(hmmm Laserallan también publicó esa respuesta 1 minuto antes :-( ;-))

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top