61 votes

Vérifier si une variable est initialisée

Il semble que ce soit un doublon, mais peut-être que c'est tellement évident que la question n'a pas été posée...

Est-ce la bonne façon de vérifier si une variable (pas un pointeur) est initialisée dans une classe C++ ?

class MyClass
{
    void SomeMethod();

    char mCharacter;
    double mDecimal;
};

void MyClass::SomeMethod()
{
    if ( mCharacter )
    {
        // do something with mCharacter.
    }

    if ( ! mDecimal )
    {
        // define mDecimal.
    }
}

41voto

Alexander Gessler Points 26717

Il n'y a aucun moyen de vérifier si le contenu d'une variable est indéfini ou non. La meilleure chose que vous puissiez faire est d'attribuer une valeur de signal/sentinelle (par exemple dans le constructeur) pour indiquer qu'une initialisation supplémentaire devra être effectuée.

24voto

littleadv Points 15607

Une variable qui n'est pas définie entraînera une erreur de compilation.

Ce que vous demandez est de vérifier si c'est initialisé . Mais l'initialisation est juste une valeur, que vous devez choisir et assigner dans le constructeur.

Par exemple :

class MyClass
{
    MyClass() : mCharacter('0'), mDecimal(-1.0){};
    void SomeMethod();

    char mCharacter;
    double mDecimal;
};

void MyClass::SomeMethod()
{
    if ( mCharacter != '0')
    {
        // touched after the constructor
        // do something with mCharacter.
    }

    if ( mDecimal != -1.0 )
    {
        // touched after the constructor
        // define mDecimal.
    }
}

Vous devriez initialiser à une valeur par défaut qui aura une signification dans le contexte de votre logique, bien sûr.

16voto

HostileFork Points 14697

En fonction de vos applications (et surtout si vous utilisez déjà Boost), vous pouvez vous intéresser à boost::optional .

(MISE À JOUR : À partir de C++17, optional fait maintenant partie de la bibliothèque standard, en tant que std::optional )

Il possède la propriété que vous recherchez, à savoir déterminer si le slot contient ou non une valeur. Par défaut, il est construit de manière à ne pas contenir de valeur et à être évalué à false, mais s'il est évalué à true, vous êtes autorisé à le déréférencer et à obtenir la valeur enveloppée.

class MyClass
{
    void SomeMethod();

    optional<char> mCharacter;
    optional<double> mDecimal;
};

void MyClass::SomeMethod()
{
    if ( mCharacter )
    {
        // do something with *mCharacter.
        // (note you must use the dereference operator)
    }

    if ( ! mDecimal )
    {
        // call mDecimal.reset(expression)
        // (this is how you assign an optional)
    }
}

Vous trouverez d'autres exemples dans la documentation de Boost .

15voto

Elmar Points 853

Avec C++17 vous pouvez utiliser std::optional pour vérifier si une variable est initialisée :

#include <optional>
#include <iostream>  // needed only for std::cout

int main() {
    std::optional<int> variable;

    if (!variable) {
        std::cout << "variable is NOT initialized\n";
    }

    variable = 3;

    if (variable) {
        std::cout << "variable IS initialized and is set to " << *variable << '\n';
    }

    return 0;
}

Ceci produira la sortie :

variable is NOT initialized
variable IS initialized and is set to 3

Pour utiliser std::optional dans l'extrait de code que vous avez fourni, vous devrez inclure l'option <optional> et ajouter l'en-tête de la bibliothèque standard std::optional<...> aux déclarations de variables respectives :

#include <optional>

class MyClass
{
    void SomeMethod();

    std::optional<char> mCharacter;
    std::optional<double> mDecimal;
};

void MyClass::SomeMethod()
{
    if ( mCharacter )
    {
        std::cout << *mCharacter;  // do something with mCharacter.
    }

    if ( ! mDecimal )
    {
        mDecimal = 3.14159;  // define mDecimal.
    }
}

4voto

Twonky Points 557

Avec les librairies C++-11 ou Boost, vous pouvez envisager de stocker la variable en utilisant des pointeurs intelligents. Considérez ce MVE où toString() le comportement dépend de bar en cours d'initialisation ou non :

#include <memory>
#include <sstream>

class Foo {

private:
    std::shared_ptr<int> bar;

public:
    Foo() {}
    void setBar(int bar) {
        this->bar = std::make_shared<int>(bar);
    }
    std::string toString() const {
        std::ostringstream ss;
        if (bar)           // bar was set
            ss << *bar;
        else               // bar was never set
            ss << "unset";
        return ss.str();
    }
};

En utilisant ce code

Foo f;
std::cout << f.toString() << std::endl;
f.setBar(42);
std::cout << f.toString() << std::endl;

produit la sortie

unset
42

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X