質問
C ++で作業していますが、スカラー値(たとえばdouble
)が<!> quot; defined <!> quot;であるかどうかを知る必要があります。か否か。また、<!> quot; undef <!> quot;必要に応じて:
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 ++では可能ですか?
ありがとう
解決
他の回答にあるように、C ++にはこの概念がありません。ただし、簡単に回避できます。
コンストラクタでbarを初期化する未定義の値を持つことができます。通常は-1.0などです。
calculate_barが負の値を返さないことがわかっている場合、<!> ltのチェックとして未定義関数を実装できます。 0.0。
より一般的な解決策は、コンストラクタでfalseに初期化されたバーがまだ定義されているかどうかを示すブール値を持ち、最初に設定したときに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;
}
他のヒント
他の人が指摘したように、<!> quot; undefined <!> quot;のようなものはありません。状態。ただし、 boost.optional
実行時に意味する場合、そのようなことはありません。 bar
が初期化されない場合、オブジェクトの割り当て方法に応じて、ランダムビットが存在します(一部のアロケーターは新しいメモリをすべてゼロに初期化します)。
編集:コンストラクターおよび/またはinit()
falseに初期化され、barの計算時にtrueに設定される個別のフラグを保持しない理由。フラグを再度falseに設定することで、「未定義」になります。
if(!isBarValid)
{
calculateBar();
isBarValid = true;
}
return bar;
C ++には<!> quot; undefined <!> quot;はありません。プリミティブ型の状態。 float / doubleに最も近いものはNANですが、実際には別の意味があります。
これはC / C ++では不可能であり、プリミティブは常に値が割り当てられます(宣言で明示的に割り当てられていない限り、ほとんどがガベージ、その前にメモリ内のその場所にあったものはすべて)。私は、未使用を示すプレースホルダー値(つまり、ポインターの場合は0)を持つのが一般的ですが、これらも明示的に割り当てる必要があります。 doubleが任意の値を取ることができる場合、最初にfalseに割り当てられたブール値をその横に配置し、計算を実行するときにその値をテスト/設定することをお勧めします。
追加のブール値を使用して実行する必要があります。
追加のブール値を使用して実装するには、次のテンプレートのようなロジックを試すことができます:
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 ...
};
初回使用イディオムで構築このようにget_bar()
と書きます:
double & get_bar()
{
static double *bar = new double(something());
return *bar;
}
bar
を呼び出すと、まだ誰も要求していない場合にdouble &
が作成されます。後続の呼び出しは、単に<=>を返します。リンクされたページにあるように、プログラムが終了するとOSがメモリを再利用するため、技術的にメモリリークはありません。
更新:
<=>を変更できるように戻り値を<=>に変更しました。
bar
をコンストラクターでsomething()
関数を呼び出したときに決して発生しない値に初期化します。
例:
Foo(): bar(-1)
{
}
次に、-1
関数の値get_bar
を確認します。
(hmmm Laserallanはその回答を1分前に投稿しました:-( ;-))