Checking if a variable is initialized

前端 未结 13 1410
后悔当初
后悔当初 2020-12-28 11:59

Seems like this would be a duplicate, but maybe it is just so obvious it hasn\'t been asked...

Is this the proper way of checking if a variable (not pointer) is init

相关标签:
13条回答
  • 2020-12-28 12:22

    Variable that is not defined will cause compilation error.

    What you're asking is about checking if it is initialized. But initialization is just a value, that you should choose and assign in the constructor.

    For example:

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

    You should initialize to a default value that will mean something in the context of your logic, of course.

    0 讨论(0)
  • 2020-12-28 12:22

    With C++-11 or Boost libs you could consider storing the variable using smart pointers. Consider this MVE where toString() behaviour depends on bar being initialized or not:

    #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();
        }
    };
    

    Using this code

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

    produces the output

    unset
    42
    
    0 讨论(0)
  • 2020-12-28 12:27

    If you mean how to check whether member variables have been initialized, you can do this by assigning them sentinel values in the constructor. Choose sentinel values as values that will never occur in normal usage of that variable. If a variables entire range is considered valid, you can create a boolean to indicate whether it has been initialized.

    #include <limits>
    
    class MyClass
    {
        void SomeMethod();
    
        char mCharacter;
        bool isCharacterInitialized;
        double mDecimal;
    
        MyClass()
        : isCharacterInitialized(false)
        , mDecimal( std::numeric_limits<double>::quiet_NaN() )
        {}
    
    
    };
    
    
    void MyClass::SomeMethod()
    {
        if ( isCharacterInitialized == false )
        {
            // do something with mCharacter.
        }
    
        if ( mDecimal != mDecimal ) // if true, mDecimal == NaN
        {
            // define mDecimal.
        }
    }
    
    0 讨论(0)
  • 2020-12-28 12:27

    Since MyClass is a POD class type, those non-static data members will have indeterminate initial values when you create a non-static instance of MyClass, so no, that is not a valid way to check if they have been initialized to a specific non-zero value ... you are basically assuming they will be zero-initialized, which is not going to be the case since you have not value-initialized them in a constructor.

    If you want to zero-initialize your class's non-static data members, it would be best to create an initialization list and class-constructor. For example:

    class MyClass
    {
        void SomeMethod();
    
        char mCharacter;
        double mDecimal;
    
        public:
            MyClass();
    };
    
    MyClass::MyClass(): mCharacter(0), mDecimal(0) {}
    

    The initialization list in the constructor above value-initializes your data-members to zero. You can now properly assume that any non-zero value for mCharacter and mDecimal must have been specifically set by you somewhere else in your code, and contain non-zero values you can properly act on.

    0 讨论(0)
  • 2020-12-28 12:28

    You could reference the variable in an assertion and then build with -fsanitize=address:

    void foo (int32_t& i) {
        // Assertion will trigger address sanitizer if not initialized:
        assert(static_cast<int64_t>(i) != INT64_MAX);
    }
    

    This will cause the program to reliably crash with a stack trace (as opposed to undefined behavior).

    0 讨论(0)
  • 2020-12-28 12:30

    With C++17 you can use std::optional to check if a variable is initialized:

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

    This will produce the output:

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

    To use std::optional in the code snipped you provided, you'll have to include the <optional> standard library header and add std::optional<...> to the respective variable declarations:

    #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.
        }
    }
    
    0 讨论(0)
提交回复
热议问题