7

私は C++ で作業しており、スカラー値 (たとえば a double) が「定義」されているかどうかを知る必要があります。必要に応じて、「定義を解除」できる必要もあります。

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

C++で可能ですか?

ありがとう

4

9 に答える 9

12

他の回答が言うように、C++にはこの概念がありません。ただし、簡単に回避できます。

コンストラクターでbarを初期化する未定義の値(通常は-1.0など)を使用できます。

calculate_barが負の値を返さないことがわかっている場合は、未定義の関数を<0.​​0のチェックとして実装できます。

より一般的な解決策は、コンストラクターでfalseに初期化したbarがまだ定義されているかどうかをブール値で示し、最初に設定したときにtrueに変更することです。boost::optionalはエレガントなテンプレートの方法でこれを行います。

これはあなたが持っているコード例がどのようになるかです。

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;
}
于 2009-01-23T15:17:06.770 に答える
6

他の人が指摘したように、「未定義」の状態のようなものはありません。ただし、 boost.optionalを調べたい場合があります

于 2009-01-23T15:18:07.050 に答える
3

実行時に意味するのであれば、そのようなことはありません。が初期化されない場合bar、オブジェクトの割り当て方法に応じて、ランダムなビットが発生します(一部のアロケータは新しいメモリをすべてゼロに初期化します)。

編集:コンストラクターや手動の初期化メソッドでオブジェクトの状態を処理するのはプログラマー次第です。init()

于 2009-01-23T15:13:31.207 に答える
2

C ++には、プリミティブ型の「未定義」状態はありません。float / doubleに最も近いものはNANですが、実際には別の意味があります。

于 2009-01-23T15:14:24.390 に答える
2

falseに初期化され、barの計算時にtrueに設定される別のフラグを維持してみませんか。次に、フラグを再度falseに設定することにより、「未定義」にすることができます。

if(!isBarValid)
{
    calculateBar();
    isBarValid = true;
}
return bar;
于 2009-01-23T15:17:54.867 に答える
1

これはC/C ++では不可能であり、プリミティブは常に値が割り当てられます(宣言時に明示的に割り当てられていない限り、ほとんどの場合、それ以前のメモリ内のその場所にあったものはすべてガベージです)。未使用を示すプレースホルダー値(つまり、ポインターの場合は0)を使用するのが一般的ですが、これらも明示的に割り当てる必要があります。doubleが任意の値を取ることができる場合は、その横にブール値を配置し、最初にfalseに割り当て、計算を行うときにそのブール値をテスト/設定することをお勧めします。

于 2009-01-23T15:15:49.783 に答える
1

最初の使用イディオムでコンストラクトを試して、次のように書くことができget_bar()ます。

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

誰もまだそれを求めていない場合は、あなたが電話したときにget_bar()それがあなたのために作られます. bar後続の呼び出しは を返すだけbarです。リンクされたページにあるように、プログラムの終了時に OS がメモリを再利用するため、技術的にメモリ リークは発生しません。

アップデート:

戻り値をdouble &に変更して、 を変更できるようにしましたbar

于 2009-01-23T15:28:28.743 に答える
0

コンストラクターで関数barを呼び出すときに発生することのない値に初期化します。something()

例えば:

Foo(): bar(-1)
{
}

次に-1get_bar関数の値を確認します。

(hmmm Laserallanもその回答を1分前に投稿しました:-(;-))

于 2009-01-23T15:17:56.020 に答える
0

追加のブール値を使用してそれを行う必要があります。

追加のブール値を使用して実装するには、次のテンプレートのようなロジックを試すことができます。

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 ...
};
于 2009-01-23T15:19:38.217 に答える