Checking if a variable is initialized

2019-02-07 16:21发布

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 initialized in a C++ class?

class MyClass
{
    void SomeMethod();

    char mCharacter;
    double mDecimal;
};

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

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

标签: c++ class
12条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-02-07 16:51

Depending on your applications (and especially if you're already using boost), you might want to look into boost::optional.

(UPDATE: As of C++17, optional is now part of the standard library, as std::optional)

It has the property you are looking for, tracking whether the slot actually holds a value or not. By default it is constructed to not hold a value and evaluate to false, but if it evaluates to true you are allowed to dereference it and get the wrapped value.

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

More examples are in the Boost documentation.

查看更多
甜甜的少女心
3楼-- · 2019-02-07 16:53

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.
    }
}
查看更多
干净又极端
4楼-- · 2019-02-07 16:53

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.

查看更多
一夜七次
5楼-- · 2019-02-07 16:55

There's no reasonable way to check whether a value has been initialized.

If you care about whether something has been initialized, instead of trying to check for it, put code into the constructor(s) to ensure that they are always initialized and be done with it.

查看更多
该账号已被封号
6楼-- · 2019-02-07 16:59

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.

查看更多
疯言疯语
7楼-- · 2019-02-07 16:59

By default, no you can't know if a variable (or pointer) has or hasn't been initialized. However, since everyone else is telling you the "easy" or "normal" approach, I'll give you something else to think about. Here's how you could keep track of something like that (no, I personally would never do this, but perhaps you have different needs than me).

class MyVeryCoolInteger
{
public:
    MyVeryCoolInteger() : m_initialized(false) {}

    MyVeryCoolInteger& operator=(const int integer)
    {
        m_initialized = true;
        m_int = integer;
        return *this;
    }

    int value()
    {
        return m_int;
    }

    bool isInitialized()
    {
        return m_initialized;
    }

private:
    int m_int;
    bool m_initialized;
};
查看更多
登录 后发表回答