C++ 检查变量是否已初始化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6822044/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:43:21  来源:igfitidea点击:

Checking if a variable is initialized

c++class

提问by

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?

这是检查变量(不是指针)是否在 C++ 类中初始化的正确方法吗?

class MyClass
{
    void SomeMethod();

    char mCharacter;
    double mDecimal;
};

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

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

采纳答案by Alexander Gessler

There is no way of checking of the contents of a variable are undefined or not. The best thing you can do is to assign a signal/sentinel value (for example in the constructor) to indicate that further initialization will need to be carried out.

没有办法检查变量的内容是否未定义。您可以做的最好的事情是分配一个信号/哨兵值(例如在构造函数中)以指示需要执行进一步的初始化。

回答by littleadv

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.

当然,您应该初始化为在您的逻辑上下文中具有某种意义的默认值。

回答by HostileFork says dont trust SE

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

根据您的应用程序(尤其是如果您已经在使用 boost),您可能需要查看boost::optional.

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

(更新:从 C++17 开始,可选现在是标准库的一部分,如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.

它具有您正在寻找的属性,跟踪插槽是否实际持有一个值。默认情况下,它被构造为不保存值并评估为 false,但如果评估为 true,您可以取消引用它并获取包装值。

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.

更多示例在Boost 文档中

回答by Elmar

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

使用 C++17,您可以使用std::optional检查变量是否已初始化:

#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::optionalin the code snipped you provided, you'll have to include the <optional>standard library header and add std::optional<...>to the respective variable declarations:

std::optional在您提供的代码中使用,您必须包含<optional>标准库头文件并添加std::optional<...>到相应的变量声明中:

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

回答by Twonky

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

使用 C++-11 或 Boost 库,您可以考虑使用智能指针存储变量。考虑这个 MVE,其中toString()行为取决于是否bar被初始化:

#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

回答by Chris Eberle

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

回答by Jerry Coffin

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.

如果您关心是否已初始化某些内容,而不是尝试检查它,请将代码放入构造函数中以确保它们始终被初始化并完成。

回答by Jason

Since MyClassis 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.

由于MyClass是 POD 类类型,当您创建 的非静态实例时,那些非静态数据成员将具有不确定的初始值MyClass,因此不,这不是检查它们是否已初始化为特定非零的有效方法value ...您基本上假设它们将被零初始化,事实并非如此,因为您没有在构造函数中对它们进行值初始化。

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 mCharacterand mDecimalmust have been specifically set by you somewhere else in your code, and contain non-zero values you can properly act on.

上面构造函数中的初始化列表将您的数据成员初始化为零。您现在可以正确地假设,任何非零值mCharacter,并mDecimal必须已经通过明确你别的地方在你的代码中设置,并包含非零值,你可以适当地采取行动。

回答by Praetorian

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

回答by Allan Lago

If for instance you use strings instead of chars, you might be able do something like this:

例如,如果您使用字符串而不是字符,则可以执行以下操作:

    //a is a string of length 1
    string a;
    //b is the char in which we'll put the char stored in a
    char b;
    bool isInitialized(){
      if(a.length() != NULL){
        b = a[0];
        return true;
      }else return false;
    }