web-dev-qa-db-ja.com

初期化せずに変数を比較

私はVC++で、x、y、z軸を持つ座標系を含むプロジェクトで作業しています。
変数(x、y、z値を持つポイント)が座標系に割り当てられているか、またはそのデフォルトのポイント(初期化されていない)に割り当てられているかどうかを確認しようとしています。
座標系なので、変数にデフォルト値を割り当てて、負または正、あるいはゼロにすることはできません。これらはすべて有効な値だからです。

ここでの私のアプローチは、ブール変数ポイント変数に関連付けることです。 )。ブール値が設定されている場合、ポイントは割り当てられません。次に、値を割り当ててブール値を設定できるすべてのステートメントを確認する必要があります。

今、私はかなり悪いこのアプローチで試しました、そしてあなたはそれを間違っていると考えるかもしれません。ここでは、初期化されていないfloat変数(Pointのx、y、zメンバーはfloatであるため)を取得して、Point変数のx、y、zメンバーと比較しています。
Pointが初期化されていない場合は、float変数とPointのメンバーの両方が一致し、初期化されていないことを宣言できます。さまざまなコンパイラでこれをテストしようとしましたが、期待どおりの結果が得られました。
明らかに、比較に使用される初期化されていない変数に対してコンパイラ警告が表示されます

私の質問、2番目のアプローチは本当に悪いですか、それともこれに対する回避策はありますか?.

4
Shirish11

Boost :: optionalまたは同様の機能を使用してみませんか?

boost::optional<point> point;

if(point)
    //is init.

独自のテンプレートクラスを作成することもできますが、個別のboolフラグを設定すると、「null許容」ポイントが必要なすべての場所で名前空間が乱雑になるため、あまり適切ではありません。また、ポイントとブール値がグループ化/属していることも意味的に明らかではありません。特に、複数の人が開発のさまざまなポイントでコードを表示している場合などです。

ポイントクラスに配置することは、100%意味的に正しいimoではありません。ポイントはポイントであるため、コンポジションを使用してこの種のものを表す方が適切です。ブール値をグループ化するテンプレート化された「ホルダー」とレイヤー化すると、何が起こるかは明らかです。ポイントが必要な他の場所では、ポイントをそのまま使用します。

5
Max

初期化されていない変数常にには値があります-それはあなたにとって何の役にも立たない値になるのではなく、その特定のチャンクが最後にメモリに残った値になりますのメモリが使用されていました。コンパイラは、比較で初期化されていない変数を使用した場合の影響が未定義で予測できない動作になることを警告しています。

Pointオブジェクトが座標が有効かどうかを示す内部状態を表す必要がある場合は、Pointクラスにboolを追加するという最初のアイデアがより信頼できるソリューションになります。 何かをチェックする必要があるので、なぜブール値を追加したくないのですか? Pointクラスに内部状態を与えると、状態を内部的に検証することもできます。これは、状態ゲッターを使用するか、例外をスローすることで実現できます。

4
Ben Cottrell

コンパイラがサポートしていれば、初期化されていない座標を使用する代わりに、座標をNaNに初期化できます( ここ を参照)。

そうすれば、点がundefinedであるか、それが3次元空間の実際の点を表すかが常にわかります。

4
Giorgio

Pointを初期化するときに座標を要求できない原因はありますか?クラスは次のようになります。

class Point {
public:
    Point( float x, float y, float z )
        : _x( x ), _y( y ), _z( z ) {}

    // Getters/setters as needed    

private:
    float _x, _y, _z;
}

この時点では、おそらく有効な初期値がないとオブジェクトを作成する方法はありません。

このアプローチでは、初期化されていないPoint変数がどこかに必要な場合は、ポインターを使用する必要があります。 NULL(またはnullptr)へのポインターを初期化する一般的な方法に従っている場合、Pointへの有効なポインターがあるときはいつでも、有効な座標のセットがあります。

2
derekerdmann

2つ目のアプローチは本当に悪いと思います。

最初に、x、y、z座標の有効な値が使用可能な場合にのみ、Pointオブジェクトのインスタンス化を可能にするように設計を変更できるかどうかを検討します。 3つのパラメーターすべてを受け取るコンストラクターを1つだけ提供します。

次に、座標を設定する単一の方法があることを検討してください。

void setCoordinates(float x, float y, float z)

このメソッドでは、有効な値をマークするために使用している状態変数を設定します。