Pergunta

Eu estou trabalhando em C ++ e eu preciso saber se um valor escalar (por exemplo, um double) está "definido" ou não. Eu também preciso ser capaz de "undef"-lo se necessário:

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

É possível em C ++?

Graças

Foi útil?

Solução

Como as outras respostas diz, C ++ não tem esse conceito. Você pode facilmente trabalhar em torno dele embora.

Ou você pode ter um valor indefinido que você inicializa bar no construtor, normalmente -1.0 ou algo similar.

Se você sabe que calculate_bar nunca retorna valores negativos você pode implementar a função indefinida como um cheque de <0.0.

A solução mais geral é ter um bool dizendo se bar está definido ainda que você inicializado como false no construtor e quando você configurá-lo primeiro você alterá-lo para true. boost :: opcional faz isso em uma maneira elegante templated.

Isto é o que o exemplo de código que você tem seria semelhante.

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

Outras dicas

Como outros apontaram, não há nada como um estado "indefinido". Mas você pode querer olhar em boost.optional

Se você quer dizer em tempo de execução, não existe tal coisa. Se bar nunca é inicializado, ele vai ter o que bits aleatórios acontecer para estar lá, dependendo de como o objeto é alocado (alguns allocators irá inicializar nova memória de todo-zero).

edit: é até o programador para o estado do objeto punho em construtores e / ou métodos de inicialização manual como init()

Por que não manter uma bandeira separado que é inicializado como false e, em seguida, fica definido como verdadeiro quando bar é calculado. Ele pode então ser 'undefed' definindo o sinalizador como false novamente.

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

C ++ não tem um estado de "indefinido" para tipos primitivos. O mais próximo disponível para float / double seria NAN, mas que realmente tem um significado diferente.

Isto não é possível em C / C ++, primitivas será sempre um valor atribuído (principalmente lixo, o que estava naquele local na memória antes que, a menos que explicitamente atribuído na declaração). I é comum ter um valor de espaço reservado (ou seja, 0 para ponteiros) que denota não-utilizado, no entanto estes têm de ser explicitamente atribuído também. Se a sua dupla pode assumir qualquer valor, então eu sugiro que você coloque um booleano ao lado dele, atribuído a falsa inicialmente, e teste / set que um quando você quer fazer seu cálculo.

Você deve fazê-lo usando um boolean extra.

Para implementar usando um boolean extra, você poderia tentar lógica como o modelo a seguir:

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

Você poderia tentar a Construct na primeira utilização idioma e escrever get_bar() desta maneira:

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

Quando você chama get_bar() ele vai fazer bar para você se ninguém pediu isso ainda. Todas as chamadas subseqüentes só vai voltar bar. Como a página vinculada diz, isso não tecnicamente vazar memória porque o sistema operacional irá recuperá-lo quando sai do programa.

UPDATE:

Mudou o valor de retorno para double & para permitir que você modifique bar.

Inicializar bar para algum valor que nunca pode ocorrer quando você chamar a função something() no construtor.

Por exemplo:

Foo(): bar(-1)
{
}

Em seguida, verificar o valor -1 na função get_bar.

(hmmm Laserallan também postou que a resposta de 1 minuto antes :-( ;-))

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top